Compare commits

..

89 Commits

Author SHA1 Message Date
35319dcd50 Revert "feat: 样式组件优化汇总—客户端(ci) https://jira.shanqu.cc/browse/GHZSCY-6866"
This reverts commit 7e00b1ac08.
2024-12-03 10:19:09 +08:00
1ddb1eb729 fix: 组件样式优化-1129测试-客户端 https://jira.shanqu.cc/browse/GHZSCY-7087 2024-12-03 10:19:09 +08:00
ab3e845321 fix: 样式组件优化汇总-2024/11/25-测试组-客户端 https://jira.shanqu.cc/browse/GHZSCY-7029 2024-12-03 10:15:23 +08:00
d02067b480 fix: 样式组件优化汇总-2024/11/12-测试组-客户端 https://jira.shanqu.cc/browse/GHZSCY-6981 2024-12-03 10:15:23 +08:00
7e00b1ac08 feat: 样式组件优化汇总—客户端(ci) https://jira.shanqu.cc/browse/GHZSCY-6866 2024-12-03 10:15:22 +08:00
e0c65e1abc feat: 样式组件优化汇总—客户端 https://jira.shanqu.cc/browse/GHZSCY-6866 2024-12-03 10:15:22 +08:00
cae720d4ec Merge branch 'fix/auth' into 'release'
fix: 修复未打开过光环时无法获取登录状态并授权的问题

See merge request halo/android/assistant-android!1998
2024-12-02 17:21:28 +08:00
925516724f fix: 修复未打开过光环时无法获取登录状态并授权的问题 2024-12-02 17:21:27 +08:00
f442a70bd3 Merge branch 'fix/delete_appointment_crash' into 'release'
fix:https://sentry.shanqu.cc/organizations/lightgame/issues/423693/?project=22...

See merge request halo/android/assistant-android!1997
2024-12-02 14:42:27 +08:00
9b3dab9897 fix:https://sentry.shanqu.cc/organizations/lightgame/issues/423693/?project=22... 2024-12-02 14:42:27 +08:00
21e5f2c98d Merge branch 'fix/webview_crash' into 'release'
fix: 修复某些机型启用WebView深色模式出现的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/421910

See merge request halo/android/assistant-android!1996
2024-12-02 10:57:52 +08:00
71c0cfe350 fix: 修复某些机型启用WebView深色模式出现的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/421910 2024-12-02 10:55:37 +08:00
3b8b60bc6b Merge branch 'fix/GHZSCY-7019' into 'release'
fix:【光环助手】自定义页面的搜索显示问题 https://jira.shanqu.cc/browse/GHZSCY-7019

See merge request halo/android/assistant-android!1995
2024-11-27 14:07:54 +08:00
ac59158dbb fix:【光环助手】自定义页面的搜索显示问题 https://jira.shanqu.cc/browse/GHZSCY-7019 2024-11-27 14:07:54 +08:00
5becdf2095 chore: 版本更新至 5.38.6 2024-11-27 11:42:36 +08:00
a88b49344f Merge branch 'hotfix/v5.38.5-1115/remove_registeraion_id' into 'release'
fix: 移除极光 registration_id

See merge request halo/android/assistant-android!1994
2024-11-27 10:43:19 +08:00
f34646cde8 fix: 移除极光 registration_id 2024-11-27 10:42:15 +08:00
9e8ffce772 Merge branch 'hotfix/v5.38.5-1115/vgame_config' into 'release'
fix: 修复接口请求失败时会把畅玩入口关闭的问题

See merge request halo/android/assistant-android!1993
2024-11-25 16:07:13 +08:00
008985489a fix: 修复接口请求失败时会把畅玩入口关闭的问题 2024-11-25 16:01:07 +08:00
2f3fbd3e7c Merge branch 'fix/custom_page_missing_required_view_id' into 'release'
fix:https://sentry.shanqu.cc/organizations/lightgame/issues/408589/events/edfa...

See merge request halo/android/assistant-android!1992
2024-11-25 09:26:26 +08:00
abef224830 fix:https://sentry.shanqu.cc/organizations/lightgame/issues/408589/events/edfa... 2024-11-25 09:26:26 +08:00
8feb9b788e Merge branch 'hotfix/v5.35.5-1115/auth_crash' into 'release'
fix: 修复授权登录页面的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/373402/?project=22

See merge request halo/android/assistant-android!1991
2024-11-25 09:22:52 +08:00
0a059deb44 fix: 修复授权登录页面的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/373402/?project=22 2024-11-22 10:14:27 +08:00
448160d255 Merge branch 'hotfix/v5.38.4-1114/va' into 'release'
fix: 修复混淆把这个方法移除了。

See merge request halo/android/assistant-android!1990
2024-11-21 14:45:54 +08:00
533f93a340 fix: 修复混淆把这个方法移除了。 2024-11-21 14:44:58 +08:00
d80b8a97a3 chore: 版本更新至 5.38.5 2024-11-21 11:50:17 +08:00
f2e6d98788 Merge branch 'feat/GHZSCY-6923' into 'release'
feat: CPM微信小游戏优化第二期—客户端 https://jira.shanqu.cc/browse/GHZSCY-6923

See merge request halo/android/assistant-android!1986
2024-11-21 11:27:25 +08:00
238a83c5fe feat: CPM微信小游戏优化第二期—客户端 https://jira.shanqu.cc/browse/GHZSCY-6923 2024-11-21 11:27:25 +08:00
ca71f23363 Merge branch 'hotfix/v5.38.4-1114/GHZSCY-7004' into 'release'
fix: 神策数据库部分字段超存储上线的问题 https://jira.shanqu.cc/browse/GHZSCY-7004

See merge request halo/android/assistant-android!1989
2024-11-21 09:57:59 +08:00
c96b41c621 fix: 神策数据库部分字段超存储上线的问题 https://jira.shanqu.cc/browse/GHZSCY-7004 2024-11-21 09:57:59 +08:00
e8ee63d52c Merge branch 'hotfix/v5.38.4-1114/GHZSCY-7004' into 'release'
fix: 神策数据库部分字段超存储上线的问题 https://jira.shanqu.cc/browse/GHZSCY-7004

See merge request halo/android/assistant-android!1987
2024-11-20 11:34:56 +08:00
90359cfffd fix: 神策数据库部分字段超存储上线的问题 https://jira.shanqu.cc/browse/GHZSCY-7004 2024-11-20 10:05:28 +08:00
a3da883033 Merge branch 'revert-8c95286f' into 'release'
Revert "Merge branch 'feat/GHZSCY-6923' into 'release'"

See merge request halo/android/assistant-android!1984
2024-11-19 18:16:53 +08:00
a9f1437a52 Revert "Merge branch 'feat/GHZSCY-6923' into 'release'" 2024-11-19 18:16:53 +08:00
8c95286fe5 Merge branch 'feat/GHZSCY-6923' into 'release'
feat: CPM微信小游戏优化第二期—客户端 https://jira.shanqu.cc/browse/GHZSCY-6923

See merge request halo/android/assistant-android!1982
2024-11-19 18:12:55 +08:00
8a835a94e3 feat: CPM微信小游戏优化第二期—客户端 https://jira.shanqu.cc/browse/GHZSCY-6923 2024-11-19 16:46:05 +08:00
14ec4aed3a Merge branch 'hotfix/v5.38.4-1114/GHZSCY-7004' into 'release'
fix: 神策数据库部分字段超存储上线的问题 https://jira.shanqu.cc/browse/GHZSCY-7004

See merge request halo/android/assistant-android!1981
2024-11-19 15:37:52 +08:00
07f956a1f0 fix: 神策数据库部分字段超存储上线的问题 https://jira.shanqu.cc/browse/GHZSCY-7004 2024-11-19 15:26:12 +08:00
6ef8d04e57 Merge branch 'fix/jg_push' into 'release'
fix: 神策上报极光推送ID改为profileSet方法

See merge request halo/android/assistant-android!1980
2024-11-18 18:21:45 +08:00
30248ef205 fix: 神策上报极光推送ID改为profileSet方法 2024-11-18 18:20:40 +08:00
87b9bb0bf3 fix: 修复下载过程中 response code 为 304 时造成下载异常的问题 2024-11-18 11:35:56 +08:00
b346882bfa Merge branch 'fix/GHZSCY-6939-merge' into 'release'
fix:【光环助手】“视频横屏滑动”专题视频播放问题 https://jira.shanqu.cc/browse/GHZSCY-6939

See merge request halo/android/assistant-android!1979
2024-11-15 17:51:24 +08:00
eeddb5ea51 fix:【光环助手】“视频横屏滑动”专题视频播放问题 https://jira.shanqu.cc/browse/GHZSCY-6939 2024-11-15 16:55:35 +08:00
78f9aa3ee4 Merge branch 'hotfix/v5.38.4-1114/GHZSCY-6927' into 'release'
fix: 深色模式下富文本指定颜色无法显示的问题 https://jira.shanqu.cc/browse/GHZSCY-6927

See merge request halo/android/assistant-android!1978
2024-11-14 10:21:48 +08:00
f34ad0675d Merge branch 'hotfix/v5.38.4-1114/va' into 'release'
feat: 1. Android 8.0 以下不初始化VA。2.去掉VA的javahook。3. 去掉VA外部应用监听。

See merge request halo/android/assistant-android!1974
2024-11-12 17:24:03 +08:00
36abcc9f19 feat: 1. Android 8.0 以下不初始化VA。2.去掉VA的javahook。3. 去掉VA外部应用监听。 2024-11-12 11:17:02 +08:00
ae878eddf1 Merge branch 'hotfix/v5.38.4-1114/remove_useless_import' into 'release'
fix: 移除无用 import

See merge request halo/android/assistant-android!1971
2024-11-11 18:03:45 +08:00
ece519115b fix: 移除无用 import 2024-11-11 18:03:01 +08:00
b9e0a8e37a Merge branch 'hotfix/v5.38.4-1114/deadobject-crash' into 'release'
fix: 修复部分调用 PackageManager 相关的方法的闪退(提供异常时的回落)...

See merge request halo/android/assistant-android!1970
2024-11-11 17:35:26 +08:00
34ca8896ae fix: 修复部分调用 PackageManager 相关的方法的闪退(提供异常时的回落) https://sentry.shanqu.cc/organizations/lightgame/issues/418276/ https://sentry.shanqu.cc/organizations/lightgame/issues/417950/ 2024-11-11 17:24:40 +08:00
d6e19bfaff Merge branch 'fix/GHZSCY-6944' into 'release'
fix:【光环助手】神策埋点游戏单搜索结果点击事件游戏单标题的内容错误 https://jira.shanqu.cc/browse/GHZSCY-6944

See merge request halo/android/assistant-android!1969
2024-11-08 09:26:58 +08:00
943fb4d4e0 fix:【光环助手】神策埋点游戏单搜索结果点击事件游戏单标题的内容错误 https://jira.shanqu.cc/browse/GHZSCY-6944 2024-11-08 09:23:42 +08:00
2c5471d524 Merge branch 'fix/sentry-418688' into 'release'
fix: Sentry-418688 SearchActivity回调onSavedInstance后,调用FragmentManager的popBackStack引发的崩溃问题

See merge request halo/android/assistant-android!1968
2024-11-07 13:42:39 +08:00
cf527db60e fix: Sentry-418688 SearchActivity回调onSavedInstance后,调用FragmentManager的popBackStack引发的崩溃问题 2024-11-07 13:42:39 +08:00
f261991a55 fix: 深色模式下富文本指定颜色无法显示的问题 https://jira.shanqu.cc/browse/GHZSCY-6927
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2024-11-06 15:49:31 +08:00
ab66621751 chore: 版本更新至 5.38.4 2024-11-04 17:59:19 +08:00
af262c624a Merge branch 'feat/GHZSCY-6904' into 'release'
feat:【光环助手】搜索bug https://jira.shanqu.cc/browse/GHZSCY-6904

See merge request halo/android/assistant-android!1966
2024-11-04 16:28:48 +08:00
d2813ecbda feat:【光环助手】搜索bug https://jira.shanqu.cc/browse/GHZSCY-6904 2024-11-04 16:28:48 +08:00
0ea932e36d Merge branch 'hotfix/v5.38.3-1113/aidl_npe_crash' into 'release'
fix: 尝试修复aidl获取对象为空导致NPE。https://sentry.shanqu.cc/organizations/lightgame/issues/399032/?project=22

See merge request halo/android/assistant-android!1965
2024-11-04 14:35:50 +08:00
68151ed6f9 fix: 尝试修复aidl获取对象为空导致NPE。https://sentry.shanqu.cc/organizations/lightgame/issues/399032/?project=22 2024-11-04 14:34:53 +08:00
e6d2361008 Merge branch 'hotfix/v5.38.3-1113/concurrent_crash' into 'release'
fix: 修复部分 5.38.3 的线上闪退问题

See merge request halo/android/assistant-android!1964
2024-11-04 13:43:00 +08:00
570b777c8e Merge branch 'hotfix/v5.38.3-1113/crashes' into 'release'
修复Sentry上的闪退问题

See merge request halo/android/assistant-android!1963
2024-11-04 11:50:45 +08:00
0e557b2246 fix: 修复启动游戏时多线程操作闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/406116/?project=22
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2024-11-04 11:50:41 +08:00
f155440814 fix: 修复下载 exception 异常为空时的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/416995/?project=22
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2024-11-04 11:49:57 +08:00
62ba9fc7bf fix: 修复游戏详情评论页面重建时出现的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/379887/events/aa3bbc5102ed4a57b66c3c7fed5d7b34/?project=22 2024-11-04 11:26:00 +08:00
4637aa8808 fix: 修复下拉推送偶发的空指针闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/418647/events/1d426e3ceda5477c9afbc6712d335b22/?project=22 2024-11-04 11:24:08 +08:00
81998e3aad Merge branch 'fix/sentry-418235' into 'release'
fix: 畅玩启动提示弹窗游戏列表数组越界问题 https://sentry.shanqu.cc/organizations/lightgame/issues/418304/?project=22

See merge request halo/android/assistant-android!1962
2024-11-01 16:15:14 +08:00
82a8aa03ba fix: 畅玩启动提示弹窗游戏列表数组越界问题 https://sentry.shanqu.cc/organizations/lightgame/issues/418304/?project=22 2024-11-01 16:13:05 +08:00
c876711578 chore: 版本更新至 5.38.3 2024-11-01 09:37:56 +08:00
41fcee7f4d Merge branch 'feat/GHZSCY-6876' into 'release'
Resolve GHZSCY-6876 "Feat/"

See merge request halo/android/assistant-android!1961
2024-11-01 09:37:04 +08:00
0ccbc4d581 feat:一键登录SDK更新—客户端 https://jira.shanqu.cc/browse/GHZSCY-6876 2024-11-01 09:37:04 +08:00
f05fc73e3a Merge branch 'hotfix/v5.38.2-1112/binding_crash' into 'release'
fix: 修复 SearchToolbarTabWrapperFragment 页面 binding bindView 时的闪退问题...

See merge request halo/android/assistant-android!1959
2024-10-31 10:31:26 +08:00
ca3c545f26 Merge branch 'hotfix/v5.38.1-1111/GHZSCY-6855' into 'release'
fix: 神策下载按钮点击事件相关字段上报异常排查 https://jira.shanqu.cc/browse/GHZSCY-6855

See merge request halo/android/assistant-android!1958
2024-10-31 10:28:28 +08:00
226539328e fix: 修复 SearchToolbarTabWrapperFragment 页面 binding bindView 时的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/418028/?project=22
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2024-10-31 10:13:36 +08:00
bb7db78b0c Merge branch 'hotfix/v5.38.2-1112/va_launch_crash' into 'release'
fix: 修复点击畅玩启动插屏广告出现的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/418073/?project=22

See merge request halo/android/assistant-android!1957
2024-10-31 09:47:03 +08:00
ede62c5363 fix: 修复点击畅玩启动插屏广告出现的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/418073/?project=22 2024-10-31 09:44:40 +08:00
12bb6824ea Merge branch 'fix/wx_subscribe_msg_response_handle' into 'release'
fix: 修复微信开服提醒消息回调处理异常问题

See merge request halo/android/assistant-android!1955
2024-10-30 14:44:16 +08:00
15c0950754 fix: 修复微信开服提醒消息回调处理异常问题 2024-10-30 14:42:55 +08:00
f86b7fe12a Merge branch 'hotfix/v5.38.2-1112/emulator_auth' into 'release'
fix: 修复雷电模拟器网游插件登录后跳转回游戏出现的闪退问题

See merge request halo/android/assistant-android!1954
2024-10-30 14:31:22 +08:00
d12cdbd34b fix: 修复雷电模拟器网游插件登录后跳转回游戏出现的闪退问题 2024-10-30 14:31:22 +08:00
8436d4eda3 Merge branch 'hotfix/v5.38.2-1112/multi_tab_loading' into 'release'
fix: 修复多tab导航页loading动画没有显示的问题

See merge request halo/android/assistant-android!1952
2024-10-29 13:51:10 +08:00
be832037a7 fix: 修复多tab导航页loading动画没有显示的问题 2024-10-29 13:41:36 +08:00
b620257825 Merge branch 'hotfix/v5.38.2-1112/GHZSCY-6859' into 'release'
fix:【光环助手】深色模式切换显示问题 https://jira.shanqu.cc/browse/GHZSCY-6859

See merge request halo/android/assistant-android!1951
2024-10-28 17:13:30 +08:00
6c88cace99 fix:【光环助手】深色模式切换显示问题 https://jira.shanqu.cc/browse/GHZSCY-6859 2024-10-28 17:11:23 +08:00
f875fa1b14 Merge branch 'feat/GHZSCY-6828' into 'release'
feat: CPM微信小游戏一期优化—客户端 https://jira.shanqu.cc/browse/GHZSCY-6828

See merge request halo/android/assistant-android!1948
2024-10-28 14:54:49 +08:00
8076c3a70a feat: CPM微信小游戏一期优化—客户端 https://jira.shanqu.cc/browse/GHZSCY-6828 2024-10-28 14:54:49 +08:00
bebab317a3 fix: 神策下载按钮点击事件相关字段上报异常排查 https://jira.shanqu.cc/browse/GHZSCY-6855 2024-10-28 14:38:06 +08:00
c450ca570d Merge branch 'hotfix/v5.38.2-1112/GHZSCY-6854' into 'release'
fix:【光环助手】切换深色/普通模式tab字体颜色变化问题 https://jira.shanqu.cc/browse/GHZSCY-6854

See merge request halo/android/assistant-android!1950
2024-10-28 10:23:56 +08:00
d239b0755f fix:【光环助手】切换深色/普通模式tab字体颜色变化问题 https://jira.shanqu.cc/browse/GHZSCY-6854 2024-10-28 10:20:53 +08:00
73 changed files with 915 additions and 386 deletions

View File

@ -72,7 +72,6 @@ android_build:
only:
- dev
- release
- pack/update_sentry_plugin_cache
# 代码检查
sonarqube_analysis:
@ -158,4 +157,3 @@ oss-upload&send-email:
only:
- dev
- release
- pack/update_sentry_plugin_cache

View File

@ -663,7 +663,8 @@
android:name=".authorization.AuthorizationActivity"
android:exported="true"
android:launchMode="singleTask"
android:screenOrientation="portrait">
android:screenOrientation="portrait"
android:taskAffinity=".auth">
<intent-filter>
<data android:scheme="ghzhushou_authorization" />
<category android:name="android.intent.category.DEFAULT" />

View File

@ -114,8 +114,6 @@ public class Config {
if (!TextUtils.isEmpty(json)) {
mSettingsEntity = GsonUtils.fromJson(json, SettingsEntity.class);
}
mSettingsEntity.setGameSmooth("off");
} catch (Exception e) {
e.printStackTrace();
}

View File

@ -287,19 +287,11 @@ public class BindingAdapters {
});
break;
case RESERVED:
if ("download".equals(gameEntity.getReserveStatus())) {
ReservationHelper.showDeleteReservationDialog(progressBar.getContext(), () -> {
ReservationHelper.deleteReservation(gameEntity, () -> {
updateReservation(progressBar, gameEntity);
});
ReservationHelper.showCancelReservationDialog(progressBar.getContext(),gameEntity, () -> {
ReservationHelper.cancelReservation(gameEntity, () -> {
updateReservation(progressBar, gameEntity);
});
} else {
ReservationHelper.showCancelReservationDialog(progressBar.getContext(),gameEntity, () -> {
ReservationHelper.cancelReservation(gameEntity, () -> {
updateReservation(progressBar, gameEntity);
});
});
}
});
break;
case H5_GAME:
LinkEntity linkEntity = gameEntity.getH5Link();

View File

@ -31,6 +31,7 @@ class ExposureListener(var fragment: Fragment, var exposable: IExposable) : Recy
override fun onFragmentPaused(fm: FragmentManager, f: Fragment) {
if (fragment == f) {
visibleState?.let { commitExposure(it) }
visibleState?.let { commitWXCPMExposure(it) }
throttleBus.clear()
}
}

View File

@ -0,0 +1,74 @@
package com.gh.common.fragment
import androidx.fragment.app.FragmentManager
import java.lang.reflect.Field
fun FragmentManager.popBackStackAllowStateLoss() {
popBackStackAllowStateLoss(-1, 0)
}
fun FragmentManager.popBackStackAllowStateLoss(id: Int, flags: Int) {
if (!isStateSaved) {
popBackStack(id, flags)
} else {
hook { popBackStack(id, flags) }
}
}
fun FragmentManager.popBackStackAllowStateLoss(name: String?, flags: Int) {
if (!isStateSaved) {
popBackStack(name, flags)
} else {
hook { popBackStack(name, flags) }
}
}
fun FragmentManager.popBackStackImmediateAllowStateLoss() = popBackStackAllowStateLoss(-1, 0)
fun FragmentManager.popBackStackImmediateAllowStateLoss(id: Int, flags: Int) =
if (!isStateSaved) {
popBackStackImmediate(id, flags)
} else {
hook { popBackStackImmediate(id, flags) }
}
fun FragmentManager.popBackStackImmediateAllowStateLoss(name: String?, flags: Int): Boolean =
if (!isStateSaved) {
popBackStackImmediate(name, flags)
} else {
hook { popBackStackImmediate(name, flags) }
}
/**
* 通过反射将FragmentManager的mStateSaved和mStopped设为false否则Activity在回调onSavedInstance以后
* 调用Fragment的popBackStack和popBackStackImmediate方法会触发“java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState”的异常。
* @see <a href="https://sentry.shanqu.cc/organizations/lightgame/issues/418688/?project=22">Sentry-418688</a>
*/
private fun <T> FragmentManager.hook(callback: FragmentManager.() -> T): T {
val mStateSavedField = getField(this::class.java,"mStateSaved")
val stateSaved = mStateSavedField.get(this);
mStateSavedField.set(this, false)
val mStoppedField = getField(this::class.java,"mStopped")
val stopped = mStateSavedField.get(this);
mStoppedField.set(this, false)
val result = callback.invoke(this)
mStateSavedField.set(this, stateSaved)
mStoppedField.set(this, stopped)
return result
}
@Throws(NoSuchFieldException::class)
private fun getField(clazz: Class<*>, name: String): Field {
var cls: Class<*>? = clazz
while (cls != null) {
try {
val declaredField = cls.getDeclaredField(name)
declaredField.isAccessible = true
return declaredField
} catch (e: NoSuchFieldException) {
e.printStackTrace()
}
cls = cls.superclass
}
throw NoSuchFieldException()
}

View File

@ -1,12 +1,9 @@
package com.gh.common.iinterface
interface ISmartRefreshContent {
/**
* 启用/关闭 页面滑动
* @param isScrollEnabled 是否启用
*/
fun setScrollEnabled(isScrollEnabled: Boolean)
import com.scwang.smartrefresh.layout.api.RefreshLayout
import com.scwang.smartrefresh.layout.constant.RefreshState
interface ISmartRefreshContent {
fun onRefresh()
/**
@ -14,4 +11,6 @@ interface ISmartRefreshContent {
* @param isSwipeRefreshEnabled 是否启用
*/
fun setSwipeRefreshEnabled(isSwipeRefreshEnabled: Boolean)
fun onStateChanged(refreshLayout: RefreshLayout, oldState: RefreshState, newState: RefreshState)
}

View File

@ -115,6 +115,12 @@ class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider {
"本地下载"
}
// 小游戏的启动不需要上报下载点击事件
// @see https://jira.shanqu.cc/browse/GHZSCY-7013
if (boundedObject is GameEntity && boundedObject.isMiniGame()) {
return
}
// 上报神策点击事件
val customPageKV = customPageTrackData?.toKV() ?: arrayOf()
SensorsBridge.trackEventWithExposureSource(
@ -124,7 +130,7 @@ class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider {
"game_name", gameName,
"game_type", gameTypeInChinese,
"download_status", downloadStatusInChinese,
"button_name", downloadButton.text,
"button_name", text,
"game_schema_type", gameSchemaType,
"download_type", downloadType,
"page_name", GlobalActivityManager.getCurrentPageEntity().pageName,

View File

@ -16,6 +16,7 @@ import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.common.constant.RouteConsts;
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
import com.gh.gamecenter.common.retrofit.BiResponse;
import com.gh.gamecenter.common.utils.SensorsBridge;
import com.gh.gamecenter.core.AppExecutor;
import com.gh.gamecenter.core.provider.ISentryProvider;
import com.gh.gamecenter.core.utils.GsonUtils;
@ -39,6 +40,11 @@ import io.reactivex.schedulers.Schedulers;
*/
public class DataUtils {
// 神策 OAID 是否已绑定
private static boolean isSensorOAIDBounded = false;
// 原始的 OAID 是否已成功获取
private static boolean originalOAIDIsReceived = false;
private DataUtils() {
throw new IllegalStateException("Utility class");
}
@ -65,7 +71,6 @@ public class DataUtils {
// 默认用 APP 级已存储的 GID 来使用,不使用外部 GID
String savedGid = SPUtils.getString(Constants.GID);
if (!TextUtils.isEmpty(savedGid)) {
HaloApp.getInstance().setGid(savedGid);
onGidReceived(savedGid);
} else {
GidHelper.getInstance().registerDevice(HaloApp.getInstance().getApplication(), new GidCallback() {
@ -89,6 +94,8 @@ public class DataUtils {
}
private static void onGidReceived(String gid) {
bindValidOaidToSensor(false);
HaloApp.getInstance().setGid(gid);
// 更新广告配置
AdDelegateHelper.INSTANCE.requestAdConfig(false, "", null);
@ -111,6 +118,35 @@ public class DataUtils {
});
}
/**
* 为神策绑定有效的 OAID
*/
public static void bindValidOaidToSensor(boolean fromOaidResult) {
if (isSensorOAIDBounded) return;
String oaid = HaloApp.getInstance().getOAID();
// 来自于 oaid 获取回调,或者说原始 oaid 已经获取成功
if (fromOaidResult || originalOAIDIsReceived) {
originalOAIDIsReceived = true;
// 遇到异常的 OAID
if (Constants.INVALID_OAID_1.equals(oaid)
|| Constants.INVALID_OAID_2.equals(oaid)
|| Constants.INVALID_OAID_3.equals(oaid)
|| TextUtils.isEmpty(oaid)) {
// 若 gid 不为空,那么整合 gid 作为 oaid https://jira.shanqu.cc/browse/GHZSCY-7004
if (HaloApp.getInstance().getGid() != null) {
oaid = "GID" + HaloApp.getInstance().getGid();
SensorsBridge.INSTANCE.setOAID(oaid);
isSensorOAIDBounded = true;
}
} else {
SensorsBridge.INSTANCE.setOAID(oaid);
isSensorOAIDBounded = true;
}
}
}
/**
* 获取应用 gid 绑定的实名信息
*/

View File

@ -139,6 +139,7 @@ public class DetailDownloadUtils {
// 游戏包含多 APK 的情况
viewHolder.getMultiVersionDownloadTv().setText("选择下载你的版本" + (TextUtils.isEmpty(downloadAddWord) ? "" : "-" + downloadAddWord));
viewHolder.getMultiVersionDownloadTv().setVisibility(View.VISIBLE);
viewHolder.getDownloadPb().setTag(com.gh.gamecenter.feature.R.string.download, viewHolder.getMultiVersionDownloadTv().getText());
viewHolder.getDownloadPb().setText("");
viewHolder.getDownloadPb().setButtonStyle(DownloadButton.ButtonStyle.NORMAL);
DownloadEntity downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity);

View File

@ -839,34 +839,25 @@ object DownloadItemUtils {
} else {
allStateClickCallback?.onCallback()
clickCallback?.onCallback()
if ("download" == gameEntity.reserveStatus) {
ReservationHelper.showDeleteReservationDialog(context) {
ReservationHelper.deleteReservation(gameEntity) {
adapter?.notifyItemChanged(position)
refreshCallback?.onCallback()
}
ReservationHelper.showCancelReservationDialog(context, gameEntity, {
NewFlatLogUtils.logMyGameCancelReserveDialogClick(
"确定取消",
gameEntity.id,
gameEntity.name ?: ""
)
ReservationHelper.cancelReservation(gameEntity) {
adapter?.notifyItemChanged(position)
refreshCallback?.onCallback()
}
} else {
ReservationHelper.showCancelReservationDialog(context, gameEntity,{
}, object : CancelListener {
override fun onCancel() {
NewFlatLogUtils.logMyGameCancelReserveDialogClick(
"确定取消",
"关闭弹窗",
gameEntity.id,
gameEntity.name ?: ""
)
ReservationHelper.cancelReservation(gameEntity) {
adapter?.notifyItemChanged(position)
refreshCallback?.onCallback()
}
}, object : CancelListener {
override fun onCancel() {
NewFlatLogUtils.logMyGameCancelReserveDialogClick(
"关闭弹窗",
gameEntity.id,
gameEntity.name ?: ""
)
}
})
}
}
})
}
}
return

View File

@ -284,7 +284,12 @@ object PackageInstaller {
installIntent.setDataAndType(uri, "application/vnd.android.package-archive")
}
updateSystemInstallerIfAvailable(context, installIntent)
// 优选系统的安装器(遇到 Exception 就回落到正常的安装器)
try {
updateSystemInstallerIfAvailable(context, installIntent)
} catch (ignored: Exception) {
// ignored
}
InstallUtils.getInstance()
.addInstall(PackageUtils.getPackageNameByPath(context, path))

View File

@ -7,7 +7,7 @@ import com.gh.gamecenter.common.utils.isVGameDownloadInDualDownloadMode
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.GameInstall
import com.gh.gamecenter.packagehelper.PackageRepository
import com.gh.gamecenter.manager.PackagesManager
import com.gh.vspace.VHelper
object PackageLauncher {
@ -91,7 +91,7 @@ object PackageLauncher {
val gameInstall = if (gameEntity != null) {
GameInstall.transformGameInstall(gameEntity, packageName)
} else {
PackageRepository.gameInstalled.find { it.packageName == packageName }
PackagesManager.getInstalledList().find { it.packageName == packageName }
}
if (gameInstall != null) {

View File

@ -14,7 +14,6 @@ import android.os.Build;
import android.os.Bundle;
import android.os.PowerManager;
import android.text.TextUtils;
import android.util.AndroidException;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -29,9 +28,9 @@ import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.common.utils.ExtensionsKt;
import com.gh.gamecenter.core.utils.MD5Utils;
import com.gh.gamecenter.entity.GameUpdateEntity;
import com.gh.gamecenter.feature.entity.ApkEntity;
import com.gh.gamecenter.feature.entity.GameEntity;
import com.gh.gamecenter.entity.GameUpdateEntity;
import com.gh.gamecenter.feature.utils.SentryHelper;
import com.gh.gamecenter.manager.PackagesManager;
import com.gh.vspace.VHelper;
@ -542,10 +541,8 @@ public class PackageUtils {
try {
Intent intent = context.getApplicationContext().getPackageManager().getLaunchIntentForPackage(packageName);
return intent != null;
} catch (IllegalArgumentException exception) {
// 一些设备调用获取 intent 的时候会触发 Parcel.readException !
exception.printStackTrace();
return false;
} catch (Exception exception) {
return PackageHelper.INSTANCE.getLocalPackageNameSet().contains(packageName);
}
}
@ -645,6 +642,19 @@ public class PackageUtils {
return 0;
}
/*
* 获取应用的名称
*/
public static CharSequence getNameByPackageName(Context context, String packageName) {
try {
PackageManager packageManager = context.getApplicationContext().getPackageManager();
return packageManager.getApplicationLabel(packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA));
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
/*
* 获取应用的 icon

View File

@ -29,53 +29,31 @@ import okhttp3.ResponseBody
object ReservationHelper {
@JvmStatic
fun deleteReservation(game: GameEntity, refreshCallback: EmptyCallback) {
deleteOrCancelReservation(game, true, refreshCallback)
}
@JvmStatic
fun cancelReservation(game: GameEntity, refreshCallback: EmptyCallback) {
deleteOrCancelReservation(game, false, refreshCallback)
}
@SuppressLint("CheckResult")
private fun deleteOrCancelReservation(
@JvmStatic
fun cancelReservation(
game: GameEntity,
deleteReservation: Boolean,
refreshCallback: EmptyCallback
) {
val retrofit = RetrofitManager.getInstance()
val single = if (deleteReservation) {
retrofit.newApi
.deleteGameReservation(
game.id,
getReserveRequestBody(game, context = HaloApp.getInstance().application)
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
} else {
retrofit.newApi
.cancelGameReservation(
game.id,
getReserveRequestBody(game, context = HaloApp.getInstance().application)
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
retrofit.newApi
.cancelGameReservation(
game.id,
getReserveRequestBody(game, context = HaloApp.getInstance().application)
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<ResponseBody>() {
override fun onSuccess(data: ResponseBody) {
ReservationRepository.removeReservationFromMemoryAndRefresh(game.id)
refreshCallback.onCallback()
}
single.subscribe(object : BiResponse<ResponseBody>() {
override fun onSuccess(data: ResponseBody) {
ReservationRepository.removeReservationFromMemoryAndRefresh(game.id)
refreshCallback.onCallback()
}
override fun onFailure(exception: Exception) {
Utils.toast(HaloApp.getInstance().application, exception.message)
exception.printStackTrace()
}
})
override fun onFailure(exception: Exception) {
Utils.toast(HaloApp.getInstance().application, exception.message)
exception.printStackTrace()
}
})
}
@JvmStatic
@ -146,21 +124,6 @@ object ReservationHelper {
})
}
@JvmStatic
fun showDeleteReservationDialog(context: Context, emptyCallback: EmptyCallback) {
DialogUtils.showCancelOrDeleteReservationDialog(
context,
"删除预约",
"游戏已上线,你可以删除此预约记录,确定删除吗?",
"确定删除",
"暂不删除", object : ConfirmListener {
override fun onConfirm() {
emptyCallback.onCallback()
}
}, null
)
}
@JvmStatic
fun showCancelReservationDialog(context: Context, game: GameEntity?, emptyCallback: EmptyCallback) {
showCancelReservationDialog(context, game, emptyCallback, null)

View File

@ -1045,6 +1045,7 @@ public class MainActivity extends BaseActivity {
blackList.add(R.id.historyTv);
blackList.add(R.id.myCollectionTv);
blackList.add(R.id.searchTv);
blackList.add(R.id.subject_tab);
updateStaticView(view, blackList);
View communityHomeWrapper = view.findViewById(R.id.communityHomeContainer);

View File

@ -15,6 +15,7 @@ import androidx.core.widget.doAfterTextChanged
import androidx.core.widget.doOnTextChanged
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction
import com.gh.common.fragment.popBackStackAllowStateLoss
import com.gh.common.util.DataCollectionUtils
import com.gh.common.util.LogUtils
import com.gh.gamecenter.DisplayType.*
@ -381,7 +382,7 @@ open class SearchActivity : BaseActivity() {
}
protected fun popBackToFragment(tag: String) {
supportFragmentManager.popBackStack(tag, 0)
supportFragmentManager.popBackStackAllowStateLoss(tag, 0)
}
@Subscribe(threadMode = ThreadMode.MAIN)

View File

@ -282,11 +282,11 @@ class SplashScreenActivity : BaseActivity() {
SensorsBridge.init(HaloApp.getInstance(), HaloApp.getInstance().channel)
SensorsBridge.setOAID(HaloApp.getInstance().oaid)
val pushProvider = ARouter.getInstance().build(RouteConsts.provider.push).navigation() as? IPushProvider
val registrationId = pushProvider?.getRegistrationId(this)
if (!registrationId.isNullOrEmpty()) {
SensorsBridge.profileAppend(KEY_REGISTRATION_ID, registrationId)
}
// val pushProvider = ARouter.getInstance().build(RouteConsts.provider.push).navigation() as? IPushProvider
// val registrationId = pushProvider?.getRegistrationId(this)
// if (!registrationId.isNullOrEmpty()) {
// SensorsBridge.profileSet(KEY_REGISTRATION_ID, registrationId)
// }
}
private fun prefetchData() {

View File

@ -455,17 +455,9 @@ class DetailViewHolder(
}
ButtonStyle.RESERVED -> {
if ("download" == mGameEntity.reserveStatus) {
ReservationHelper.showDeleteReservationDialog(mViewHolder.context) {
ReservationHelper.deleteReservation(mGameEntity) {
DetailDownloadUtils.updateViewHolder(mViewHolder)
}
}
} else {
ReservationHelper.showCancelReservationDialog(mViewHolder.context, mGameEntity) {
ReservationHelper.cancelReservation(mGameEntity) {
DetailDownloadUtils.updateViewHolder(mViewHolder)
}
ReservationHelper.showCancelReservationDialog(mViewHolder.context, mGameEntity) {
ReservationHelper.cancelReservation(mGameEntity) {
DetailDownloadUtils.updateViewHolder(mViewHolder)
}
}
}

View File

@ -1,11 +1,13 @@
package com.gh.gamecenter.authorization
import android.app.Dialog
import android.content.Intent
import android.os.Build
import android.os.Bundle
import com.gh.common.util.CheckLoginUtils
import com.gh.common.util.DialogUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.common.util.PackageUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.activity.ToolBarActivity
import com.gh.gamecenter.common.constant.EntranceConsts
@ -16,6 +18,7 @@ import com.gh.gamecenter.common.utils.viewModelProvider
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.databinding.ActivityAuthorizationBinding
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.login.user.UserRepository
import com.gh.gamecenter.login.view.LoginActivity
import com.gh.vspace.VHelper
import com.lightgame.utils.Utils
@ -68,6 +71,8 @@ class AuthorizationActivity : ToolBarActivity() {
//授权token
private var mToken = ""
private var loadingDialog: Dialog? = null
override fun getLayoutId(): Int {
return R.layout.activity_authorization
}
@ -80,11 +85,16 @@ class AuthorizationActivity : ToolBarActivity() {
mBinding = ActivityAuthorizationBinding.bind(mContentView)
checkParam()
initView()
mBinding.authorizeBtn.postDelayed({
mBaseHandler.post {
if (loadingDialog == null) {
loadingDialog = DialogUtils.showWaitDialog(this, "请稍后...")
}
}
UserRepository.getInstance().loginUserInfo.observe(this) {
checkLogin {
initUserInfo()
}
}, 500)
}
NewFlatLogUtils.logLoginFromGHZSShow(
gameId = gameId,
gameName = gameName
@ -97,14 +107,21 @@ class AuthorizationActivity : ToolBarActivity() {
}
private fun initData() {
if (mToken.isNotEmpty() || isFinishing) return
val loadingDialog = DialogUtils.showWaitDialog(this, "请稍后...")
if (mToken.isNotEmpty() || isFinishing) {
loadingDialog?.dismiss()
return
}
if (loadingDialog == null) {
loadingDialog = DialogUtils.showWaitDialog(this, "请稍后...")
} else if (loadingDialog?.isShowing == false) {
loadingDialog?.show()
}
mViewModel.getAccessToken(listOf(mContent), {
mToken = it
loadingDialog.dismiss()
loadingDialog?.dismiss()
}, {
toast("获取token失败")
loadingDialog.dismiss()
loadingDialog?.dismiss()
})
}
@ -152,8 +169,8 @@ class AuthorizationActivity : ToolBarActivity() {
private fun initView() {
//通过包名获取app图标和名称
val pkgName = mRemotePkgName ?: return
val icon = packageManager.getApplicationIcon(pkgName)
val name = packageManager.getApplicationLabel(packageManager.getApplicationInfo(pkgName, 0))
val icon = PackageUtils.getIconByPackageName(this, pkgName)
val name = PackageUtils.getNameByPackageName(this, pkgName)
mBinding.authorizeAppIcon.setImageDrawable(icon)
mBinding.authorizeAppName.text = name
mBinding.authorizeBtn.setOnClickListener {
@ -242,10 +259,10 @@ class AuthorizationActivity : ToolBarActivity() {
VHelper.launch(this, gamePkg, ignoreGApps = true, showLoading = showLoading)
return
}
val remotePkgName = this.mRemotePkgName
if (remotePkgName != null) {// 跳转回其他授权app
startActivity(packageManager.getLaunchIntentForPackage(remotePkgName))
}
// val remotePkgName = this.mRemotePkgName
// if (remotePkgName != null) {// 跳转回其他授权app
// startActivity(packageManager.getLaunchIntentForPackage(remotePkgName))
// }
}
override fun onBackPressed() {

View File

@ -18,7 +18,13 @@ data class SearchSubjectEntity(
@SerializedName("ad_icon_active")
val adIconActive: Boolean = false,
// 本地字段标记是否为微信小游戏CPM专题
var isWGameSubjectCPM: Boolean = false
var isWGameSubjectCPM: Boolean = false,
val type: String = ""
) : Parcelable {
companion object {
const val TYPE_WECHAT_GAME_CPM_COLUMN = "wechat_game_cpm_column"
}
fun getFilterGame() = RegionSettingHelper.filterGame(games)
}

View File

@ -866,10 +866,11 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
showConcernIconAtBottomBarIfAvailable()
val downloadEntitySnapshot = DownloadManager.getInstance().getDownloadEntitySnapshot(mGameEntity)
val downloadEntitySnapshot = DownloadManager.getInstance().getDownloadEntitySnapshot(mGameEntity)
if (isSpecialDownloadDialogAvailable(downloadEntitySnapshot)
&& downloadEntitySnapshot != null) {
&& downloadEntitySnapshot != null
) {
updateSpecialDownloadDialogIcon(true)
}
@ -1855,19 +1856,10 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
)
} else {
if ("download" == mGameEntity?.reserveStatus) {
ReservationHelper.showDeleteReservationDialog(requireContext()) {
ReservationHelper.deleteReservation(mGameEntity!!) {
DetailDownloadUtils.updateViewHolder(detailViewHolder)
showReserveBtn(isShowReserveBtn())
}
}
} else {
ReservationHelper.showCancelReservationDialog(requireContext(), mGameEntity) {
ReservationHelper.cancelReservation(mGameEntity!!) {
DetailDownloadUtils.updateViewHolder(detailViewHolder)
showReserveBtn(isShowReserveBtn())
}
ReservationHelper.showCancelReservationDialog(requireContext(), mGameEntity) {
ReservationHelper.cancelReservation(mGameEntity!!) {
DetailDownloadUtils.updateViewHolder(detailViewHolder)
showReserveBtn(isShowReserveBtn())
}
}
}

View File

@ -983,14 +983,17 @@ class DescAdapter(
setExpandMaxLines(maxDesLines)
setIsExpanded(Int.MAX_VALUE == maxDesLines)
if (customColumn.isHtmlDes == true) {
val decoratedDesBrief = (customColumn.desBrief ?: "").dropFontColorInDarkMode(contentTv.context)
val decoratedDes = (customColumn.des ?: "").dropFontColorInDarkMode(contentTv.context)
shrankSpanned = HtmlCompat.fromHtml(
customColumn.desBrief ?: "",
decoratedDesBrief,
HtmlCompat.FROM_HTML_MODE_COMPACT,
PicassoImageGetter(contentTv),
ExtraTagHandler()
)
expandedSpanned = HtmlCompat.fromHtml(
customColumn.des ?: "",
decoratedDes,
HtmlCompat.FROM_HTML_MODE_COMPACT,
PicassoImageGetter(contentTv),
ExtraTagHandler()

View File

@ -25,10 +25,10 @@ import com.gh.gamecenter.common.utils.toPx
import com.gh.gamecenter.core.iinterface.IScrollable
import com.gh.gamecenter.core.utils.MtaHelper
import com.gh.gamecenter.core.utils.SpanBuilder
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.entity.RatingComment
import com.gh.gamecenter.eventbus.EBStar
import com.gh.gamecenter.eventbus.EBTypeChange
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.gamedetail.GameDetailFragment
import com.halo.assistant.HaloApp
import org.greenrobot.eventbus.EventBus
@ -60,7 +60,7 @@ class RatingFragment : LazyListFragment<RatingComment, RatingViewModel>(), IScro
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == RATING_EDIT_REQUEST && resultCode == Activity.RESULT_OK) {
mListViewModel.initData()
mListViewModel?.initData()
} else if (
(requestCode == RATING_REPLAY_REQUEST || requestCode == RATING_PATCH_REQUEST)
&& resultCode == Activity.RESULT_OK

View File

@ -3,7 +3,11 @@ package com.gh.gamecenter.home.custom
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.RelativeLayout
import androidx.core.view.updateLayoutParams
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.RecyclerView
@ -54,6 +58,7 @@ import com.gh.gamecenter.feature.entity.PageLocation
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.exposure.ExposureType
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.feature.utils.SentryHelper
import com.gh.gamecenter.game.commoncollection.detail.CustomCommonCollectionDetailActivity
import com.gh.gamecenter.gamedetail.rating.RatingReplyActivity
import com.gh.gamecenter.home.PageConfigure
@ -69,6 +74,9 @@ import com.gh.gamecenter.wrapper.SearchToolbarTabWrapperViewModel
import com.halo.assistant.HaloApp
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity
import com.scwang.smartrefresh.layout.api.RefreshLayout
import com.scwang.smartrefresh.layout.constant.RefreshState
import com.shuyu.gsyvideoplayer.video.base.GSYVideoView
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
@ -179,6 +187,22 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
viewModel.init(pageConfigure, searchToolbarTabWrapperViewModel, pageLocation)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = try {
FragmentCustomBinding.inflate(layoutInflater)
} catch (e: Exception) {
SentryHelper.onEvent(
"VIEW_BINDING_BIND_ERROR",
"digest", e.localizedMessage,
"gid", HaloApp.getInstance().gid
)
// 玄学,重试一次,该闪退闪退
FragmentCustomBinding.inflate(layoutInflater)
}
mCachedView = binding.root
return mCachedView
}
override fun getRealLayoutId() = R.layout.fragment_custom
override fun onFragmentFirstVisible() {
@ -275,6 +299,9 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
if (searchBarBinding == null) {
binding.reuseSearchBarStub.setOnInflateListener { _, inflated ->
searchBarBinding = LayoutSearchBarBinding.bind(inflated)
binding.gameRefresh.updateLayoutParams<RelativeLayout.LayoutParams> {
addRule(RelativeLayout.BELOW, R.id.reuseSearchBar)
}
initSearchBar(it)
}
binding.reuseSearchBarStub.inflate()
@ -490,8 +517,6 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
override fun initRealView() {
super.initRealView()
binding = FragmentCustomBinding.bind(mCachedView)
scrollCalculatorHelper = ScrollCalculatorHelper(binding.gameList, R.id.autoVideoView, 0, false)
buildPriorityChain()
@ -745,7 +770,7 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
}
}
override fun setScrollEnabled(isScrollEnabled: Boolean) {
private fun setScrollEnabled(isScrollEnabled: Boolean) {
if (::layoutManager.isInitialized) {
layoutManager.isScrollVerticallyEnabled = isScrollEnabled
}
@ -761,6 +786,32 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
}
}
override fun onStateChanged(refreshLayout: RefreshLayout, oldState: RefreshState, newState: RefreshState) {
if (oldState == RefreshState.None && newState == RefreshState.PullDownToRefresh) {
pauseVideo()
} else if ((oldState == RefreshState.TwoLevelFinish || oldState == RefreshState.RefreshFinish) && newState == RefreshState.None) {
val currentPlayer = scrollCalculatorHelper.currentPlayer
if (currentPlayer == null) {
scrollCalculatorHelper.playIfValid()
} else if (currentPlayer.currentState == GSYVideoView.CURRENT_STATE_PAUSE) {
resumeVideo()
}
}
when (newState) {
RefreshState.TwoLevel -> {
setScrollEnabled(false)
}
RefreshState.None -> {
setScrollEnabled(true)
}
else -> {
// do nothing
}
}
}
override fun scrollToTop() {
if (::binding.isInitialized) {
binding.gameList.stopScroll()

View File

@ -806,7 +806,7 @@ class CustomPageRepository private constructor(
fun loadChangeSubjectGame(subjectEntity: SubjectEntity): Observable<List<GameEntity>> =
if (subjectEntity.isWechatColumnCPM) {// 微信小游戏CPM专题的“换一批”接口
wGameSubjectCPMRemoteDataSource.getRecommendCPMList(2, 10).toObservable()
wGameSubjectCPMRemoteDataSource.getEditorRecommendCPMList(2, 10).toObservable()
} else {
remoteDataSource.loadChangeSubjectGame(subjectEntity)
}

View File

@ -65,7 +65,7 @@ class SubjectTracker(private val pageLocation: PageLocation) {
pageLocation.pageName,
subject?.id ?: "",
subject?.name ?: "",
"最近在玩",
"自定义页面",
item.componentStyle,
"",
)

View File

@ -363,7 +363,7 @@ class CommonContentHomeSlideWithCardsUi(
homeSlideCardItemBinding.cardIv.visibility = View.VISIBLE
// 防止重复加载图片导致闪烁
if (homeSubSlide.image != cardIv.getTag(R.string.tag_img_url_id)) {
ImageUtils.display(cardIv, homeSubSlide.image, false, AlphaGradientProcess())
ImageUtils.display(cardIv, homeSubSlide.image, true, AlphaGradientProcess())
cardIv.setTag(R.string.tag_img_url_id, homeSubSlide.image)
}
ConstraintSet().apply {
@ -398,7 +398,7 @@ class CommonContentHomeSlideWithCardsUi(
descTv.text = homeSubSlide.cardDesc
// 防止重复加载图片导致闪烁
if (homeSubSlide.image != cardIv.getTag(R.string.tag_img_url_id)) {
ImageUtils.display(cardIv, homeSubSlide.image, false, AlphaGradientProcess())
ImageUtils.display(cardIv, homeSubSlide.image, true, AlphaGradientProcess())
cardIv.setTag(R.string.tag_img_url_id, homeSubSlide.image)
}
ConstraintSet().apply {

View File

@ -40,7 +40,7 @@ class CustomGameGallerySlideViewHolder(
override fun bindView(item: CustomPageItem) {
super.bindView(item)
if (item is CustomSubjectItem) {
binding.cardView.setCardBackgroundColor(com.gh.gamecenter.common.R.color.ui_container_1.toColor(binding.root.context))
if (item.data == cachedSubject) return
cachedSubject = item.data
@ -77,7 +77,6 @@ class CustomGameGallerySlideViewHolder(
val gameList = item.data.data ?: emptyList()
(recyclerView.adapter as? GameGallerySlideAdapter)?.submitList(gameList)
}
binding.cardView.setCardBackgroundColor(com.gh.gamecenter.common.R.color.text_FAFAFA.toColor(binding.root.context))
}

View File

@ -109,7 +109,9 @@ class CustomHomeGameItemViewHolder(
item.linkColumn?.id ?: ""
)
}
binding.gameBrief.text = game.recommendText
binding.gameBrief.goneIf(game.recommendText.isEmpty()) {
binding.gameBrief.text = game.recommendText
}
binding.gameImage.visibleIf(game.showImage) {
if (game.isWechatMiniGame()) {
ImageUtils.display(binding.gameImage, game.banner)

View File

@ -41,6 +41,8 @@ class AutomaticVideoView @JvmOverloads constructor(context: Context, attrs: Attr
var thumbImage: SimpleDraweeView = findViewById(R.id.thumbImage)
var containerView: RadiusCardView = findViewById(R.id.container)
var detailBtn: TextView? = null
var isMute = true
private var mIsFirstPlay = true
private var mMuteDisposable: Disposable? = null
private var mMaskDisposable: Disposable? = null
private val mUUID = UUID.randomUUID().toString()
@ -89,10 +91,11 @@ class AutomaticVideoView @JvmOverloads constructor(context: Context, attrs: Attr
mVideoAllCallBack.onClickStartThumb(mOriginUrl, mTitle, this)
}
prepareVideo()
val topVideoVoiceStatus = SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
if (topVideoVoiceStatus) {
violenceUpdateMuteStatus()
if (mIsFirstPlay) {
isMute = SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
mIsFirstPlay = false
}
violenceUpdateMuteStatus()
resetDetailMask()
}
@ -106,15 +109,21 @@ class AutomaticVideoView @JvmOverloads constructor(context: Context, attrs: Attr
mMuteDisposable?.dispose()
mMuteDisposable = null
}
mute()
if (isMute) {
mute()
} else {
unMute()
}
}
}
fun mute() {
isMute = true
CustomManager.getCustomManager(getKey()).isNeedMute = true
}
fun unMute() {
isMute = false
CustomManager.getCustomManager(getKey()).isNeedMute = false
}

View File

@ -29,7 +29,10 @@ class ScrollCalculatorHelper(
fun enableAndPlayIfValid() {
isEnabled = true
playIfValid()
}
fun playIfValid() {
if (mListRv.isAttachedToWindow
&& mListRv.scrollState == RecyclerView.SCROLL_STATE_IDLE) {
playVideo(mListRv)

View File

@ -59,7 +59,7 @@ class MiniGameSearchDefaultRankAdapter(
_id = rank.id,
mName = rank.name,
miniGameAppId = rank.link.link ?: "",
miniGameType = Constants.WECHAT_MINI_GAME,
miniGameCategory = Constants.WECHAT_MINI_GAME,
usage = rank.usage ?: 0
)
holder.binding.playCount.visibility = View.VISIBLE

View File

@ -21,11 +21,15 @@ class MiniGameSearchResultRepository(
return api.getSearchMiniGameList(key, page, 20)
}
override fun getSearchMiniGameCPM(key: String?): Observable<List<GameEntity>> {
return Observable.just(emptyList())
}
override fun getSearchSubject(key: String?, page: Int): Observable<List<SearchSubjectEntity>> {
return Observable.just(emptyList())
}
override fun getWGameCPMGameList(): Single<MutableList<GameEntity>> {
return mWGameSubjectCPMDataSource.getRecommendCPMList(1)
return mWGameSubjectCPMDataSource.getUserRecommendCPMList()
}
}

View File

@ -11,7 +11,7 @@ class WGameSubjectCPMListRepository(
) : ISubjectListRepository {
override fun getColumn(column_id: String?, page: Int, sort: String?, order: String?): Single<MutableList<GameEntity>> {
return dataSource.getRecommendCPMList(page)
return dataSource.getEditorRecommendCPMList(page)
}
override fun getColumnSettings(column_id: String?): Observable<SubjectSettingEntity> {

View File

@ -14,7 +14,51 @@ class WGameSubjectCPMRemoteDataSource(
private val api: WGameCPMApiService = RetrofitManager.getInstance().wGameCPMApi
) {
fun getRecommendCPMList(page: Int, pageSize: Int = 10): Single<MutableList<GameEntity>> {
fun getEditorRecommendCPMList(page: Int, pageSize: Int = 10): Single<MutableList<GameEntity>> {
val meta = MetaUtil.getMeta()
val request = mapOf(
"head" to mapOf(
"busiAppid" to Config.WGAME_CPM_BUSIAPPID,
"oaid" to (meta.oaid ?: ""),
"manufacturer" to (meta.manufacturer ?: ""),
"mode" to (meta.model ?: ""),
"androidId" to (MetaUtil.getAndroidId()),
"imei" to (MetaUtil.getIMEI())
),
"body" to mapOf(
"page" to page - 1,
"pageSize" to pageSize,
)
)
return api.getEditorRecommendList(request.toRequestBody())
.map {
if (it.ret == 0) {
it.appInfoList.map { info ->
GameEntity(
mName = info.appName,
mIcon = info.logo,
mBrief = info.briefIntro,
miniGameUid = info.appID,
miniGameAppId = info.userName,
miniGameCategory = Constants.WECHAT_MINI_GAME,
profit = Constants.WECHAT_MINI_GAME_PROFIT_CPM,
miniGameAppStatus = 2,
miniGameAppPath = info.wechatAppPath,
miniGameExtData = info.extData,
miniGameRecommendId = info.recommendID,
mTagStyle = arrayListOf(
TagStyleEntity(name = info.categoryName),
TagStyleEntity(name = info.subcategoryName)
)
)
}.toMutableList()
} else {
mutableListOf()
}
}
}
fun getUserRecommendCPMList(page: Int = 1, pageSize: Int = 10): Single<MutableList<GameEntity>> {
val meta = MetaUtil.getMeta()
val request = mapOf(
"head" to mapOf(
@ -40,7 +84,8 @@ class WGameSubjectCPMRemoteDataSource(
mBrief = info.briefIntro,
miniGameUid = info.appID,
miniGameAppId = info.userName,
miniGameType = Constants.WECHAT_MINI_GAME_CPM,
miniGameCategory = Constants.WECHAT_MINI_GAME,
profit = Constants.WECHAT_MINI_GAME_PROFIT_CPM,
miniGameAppStatus = 2,
miniGameAppPath = info.wechatAppPath,
miniGameExtData = info.extData,

View File

@ -318,6 +318,12 @@ public interface ApiService {
@GET
Observable<List<GameEntity>> getSearchGame(@Url String url);
/**
* 搜索CPM微信小游戏
*/
@GET("mini_game/search/configs")
Observable<List<GameEntity>> getSearchWechatMiniCPMGame(@Query("keyword") String key);
/**
* 游戏搜索的专题数据
*/

View File

@ -8,6 +8,8 @@ import io.reactivex.Single
interface ISearchGameResultRepository {
fun getSearchGame(key: String?, page: Int): Observable<List<GameEntity>>
fun getSearchMiniGameCPM(key: String?): Observable<List<GameEntity>>
fun getSearchSubject(key: String?, page: Int): Observable<List<SearchSubjectEntity>>
fun getWGameCPMGameList(): Single<MutableList<GameEntity>>

View File

@ -86,7 +86,7 @@ class SearchSubjectItemViewHolder(var binding: SearchSubjectItemBinding) : Recyc
binding.run {
subjectRv.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
subjectRv.adapter = SearchSubjectAdapter(context, entity.getFilterGame(), "($type-专题)", key) {
subjectRv.adapter = SearchSubjectAdapter(context, entity.getFilterGame(), entity.columnId, entity.name, "($type-专题)", key) {
dao?.add(key)
if (itemData.adConfig != null) {
NewFlatLogUtils.logClickGameAd(

View File

@ -107,6 +107,7 @@ class SearchGameResultAdapter(
return when {
oldItem?.subject != null && newItem?.subject != null -> {
oldItem.subject.columnId == newItem.subject.columnId
&& oldItem.subject.games == newItem.subject.games
}
oldItem?.game != null && newItem?.game != null -> {
@ -121,6 +122,7 @@ class SearchGameResultAdapter(
return when {
oldItem?.subject != null && newItem?.subject != null -> {
oldItem.subject.columnId == newItem.subject.columnId
&& oldItem.subject.games == newItem.subject.games
}
oldItem?.game != null && newItem?.game != null -> {
@ -169,39 +171,50 @@ class SearchGameResultAdapter(
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is SearchSubjectItemViewHolder -> {
holder.binding.run {
when {
position == 0 -> topDivider.visibility = View.GONE
position > 0 -> {
val gameEntity = mEntityList[position - 1].game
if (gameEntity != null) {
val isShowTag = gameEntity.contentTag != null
&& (gameEntity.contentTag!!.custom.isNotEmpty()
|| gameEntity.contentTag!!.zone.link.isNotEmpty()
|| gameEntity.contentTag!!.isLibaoExists
|| gameEntity.contentTag!!.server)
val isShowTagByMirror =
if (gameEntity.shouldUseMirrorInfo()) isShowTag && gameEntity.obtainMirrorData()?.contentTagStatus == "on" else isShowTag
if (isShowTagByMirror) {
topDivider.visibility = View.GONE
val itemData = mEntityList[position]
if (itemData.subject == null || itemData.subject.games.isEmpty()) {
holder.binding.topDivider.visibility = View.GONE
holder.binding.bottomDivider.visibility = View.GONE
holder.binding.headContainer.root.visibility = View.GONE
holder.binding.subjectRv.visibility = View.GONE
} else {
holder.binding.headContainer.root.visibility = View.VISIBLE
holder.binding.subjectRv.visibility = View.VISIBLE
holder.binding.run {
when {
position == 0 -> topDivider.visibility = View.GONE
position > 0 -> {
val gameEntity = mEntityList[position - 1].game
if (gameEntity != null) {
val isShowTag = gameEntity.contentTag != null
&& (gameEntity.contentTag!!.custom.isNotEmpty()
|| gameEntity.contentTag!!.zone.link.isNotEmpty()
|| gameEntity.contentTag!!.isLibaoExists
|| gameEntity.contentTag!!.server)
val isShowTagByMirror =
if (gameEntity.shouldUseMirrorInfo()) isShowTag && gameEntity.obtainMirrorData()?.contentTagStatus == "on" else isShowTag
if (isShowTagByMirror) {
topDivider.visibility = View.GONE
} else {
topDivider.visibility = View.VISIBLE
}
} else {
topDivider.visibility = View.VISIBLE
topDivider.visibility = View.GONE
}
} else {
topDivider.visibility = View.GONE
}
}
bottomDivider.visibility = View.VISIBLE
}
bottomDivider.visibility = View.VISIBLE
holder.bindSubjectItem(
mContext,
itemData,
SearchType.fromString(type).toChinese(),
key,
dao,
sourceEntrance = sourceEntrance
)
}
holder.bindSubjectItem(
mContext,
mEntityList[position],
SearchType.fromString(type).toChinese(),
key,
dao,
sourceEntrance = sourceEntrance
)
}
is SearchGameFirstItemViewHolder -> {

View File

@ -10,13 +10,20 @@ import com.gh.gamecenter.retrofit.service.ApiService
import com.halo.assistant.HaloApp
import io.reactivex.Observable
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import java.net.URLEncoder
import java.util.concurrent.TimeUnit
class SearchGameResultRepository(
private val mApi: ApiService = RetrofitManager.getInstance().api,
private val mNewApi: ApiService = RetrofitManager.getInstance().newApi,
private val mWGameSubjectCPMDataSource: WGameSubjectCPMRemoteDataSource = WGameSubjectCPMRemoteDataSource()
) : ISearchGameResultRepository {
private var currentSearchKey: String? = null
private var currentMiniGameCPMSearchList: MutableList<GameEntity>? = null
override fun getSearchGame(
key: String?,
page: Int
@ -31,11 +38,26 @@ class SearchGameResultRepository(
)
}
override fun getSearchMiniGameCPM(key: String?): Observable<List<GameEntity>> {
val currentMiniGameCPMSearchList = currentMiniGameCPMSearchList
if (key == currentSearchKey && currentMiniGameCPMSearchList != null) {
return Observable.just(currentMiniGameCPMSearchList)
}
return mNewApi.getSearchWechatMiniCPMGame(key)
.timeout(5, TimeUnit.SECONDS)
.onErrorReturnItem(emptyList())
.observeOn(AndroidSchedulers.mainThread())
.doOnNext {
this.currentSearchKey = key
this.currentMiniGameCPMSearchList = it
}
}
override fun getSearchSubject(key: String?, page: Int): Observable<List<SearchSubjectEntity>> {
return mApi.getSearchSubject(key, page)
}
override fun getWGameCPMGameList(): Single<MutableList<GameEntity>> {
return mWGameSubjectCPMDataSource.getRecommendCPMList(1)
return mWGameSubjectCPMDataSource.getUserRecommendCPMList()
}
}

View File

@ -67,49 +67,60 @@ class SearchGameResultViewModel(
@SuppressLint("CheckResult")
private fun decorateListAndPost(list: MutableList<GameEntity>) {
val itemDataList = ArrayList(
list.mapIndexed { index, game ->
SearchItemData(game = game, gamePosition = index, isFirst = index == 0)
}
)
val itemDataList = ArrayList<SearchItemData>()
val combineGameList = list.toMutableList()
refreshWrongInstallStatus()
repository.getSearchSubject(mSearchKey, mPage)
.map { dataList ->
mSearchSubjects.addAll(dataList)
var cpmSearchSubject: SearchSubjectEntity? = null
mSearchSubjects.forEach {
// 微信小游戏CPM专题需要等搜索广告位插入完成后再插入
if (it.location == WGAME_CPM_SUBJECT_POSITION) {
cpmSearchSubject = it.apply { isWGameSubjectCPM = true }
repository.getSearchMiniGameCPM(mSearchKey)
.zipWith(repository.getSearchSubject(mSearchKey, mPage)) { cpmGameList, subjectList -> // CPM游戏搜索结果列表合并
for (cpmGame in cpmGameList) {
if (cpmGame.location <= 0 || cpmGame.location > list.size) {
combineGameList.add(cpmGame)
} else {
val item = SearchItemData(subject = it)
if (it.location <= 0 || it.location > itemDataList.size) {
itemDataList.add(item)
} else {
itemDataList.add(it.location - 1, item)
}
combineGameList.add(cpmGame.location - 1, cpmGame)
}
}
cpmSearchSubject to dataList
itemDataList.addAll(
combineGameList.mapIndexed { index, game ->
SearchItemData(game = game, gamePosition = index, isFirst = index == 0)
}
)
subjectList
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ result ->
.subscribe({ mutableList ->
val cpmSearchSubjects = mutableListOf<SearchSubjectEntity>()
mSearchSubjects.addAll(mutableList)
mSearchSubjects.forEach {
if (it.type == SearchSubjectEntity.TYPE_WECHAT_GAME_CPM_COLUMN) {
cpmSearchSubjects.add(it.apply { isWGameSubjectCPM = true })
}
val item = SearchItemData(subject = it)
if (it.location <= 0 || it.location > itemDataList.size) {
itemDataList.add(item)
} else {
itemDataList.add(it.location - 1, item)
}
}
// 处理初始化列表且游戏列表size为0的情况
handleLoadStatusWhenGameListIsEmpty(list, itemDataList)
if (mIsManuallySearch) {
if (mSearchKey == AdDelegateHelper.gameSearchKeyword) {
updateAdConfigAndDecorateList(itemDataList, list, result.first)
updateAdConfigAndDecorateList(itemDataList, list)
} else {
AdDelegateHelper.requestAdConfig(false, mSearchKey ?: "") {
updateAdConfigAndDecorateList(itemDataList, list, result.first)
updateAdConfigAndDecorateList(itemDataList, list)
}
}
} else {
decorateWithWGameSubjectCPM(itemDataList, list, result.first)
postResultList(itemDataList, list)
}
if (cpmSearchSubjects.isNotEmpty()) {
decorateListWithWGameCPM(cpmSearchSubjects, itemDataList, list)
}
}, {
it.printStackTrace()
@ -118,12 +129,50 @@ class SearchGameResultViewModel(
})
}
/**
* 请求微信小游戏CPM接口获取专题游戏数据并插入对应的专题项中相关需求如下
* @see <a href="https://jira.shanqu.cc/browse/GHZSCY-6710">【光环助手】CPM微信小游戏API接入工作</a>
* @see <a href="https://jira.shanqu.cc/browse/GHZSCY-6827">【光环助手】CPM微信小游戏一期优化</a>
*/
@SuppressLint("CheckResult")
private fun updateAdConfigAndDecorateList(
private fun decorateListWithWGameCPM(
subjects: List<SearchSubjectEntity>,
itemDataList: ArrayList<SearchItemData>,
list: MutableList<GameEntity>,
cpmSubjectEntity: SearchSubjectEntity?
list: MutableList<GameEntity>
) {
val subjectList = subjects.filterNot {
it.games.isNotEmpty()
}
if (subjectList.isEmpty()) return
val subjectSingleList = subjectList.map { subject ->
repository.getWGameCPMGameList()
.onErrorReturnItem(mutableListOf())
.map { subject.columnId to it }
}
Single.zip(subjectSingleList) { it.map { item -> item as Pair<String, MutableList<GameEntity>> } }
.map { dataList ->
for (index in itemDataList.indices) {
val itemData = itemDataList[index]
val subject = itemData.subject ?: continue
if (subject.games.isNotEmpty()) continue
val pair = dataList.firstOrNull { data ->
data.first == subject.columnId
} ?: continue
val newItemData = SearchItemData(
subject = subject.copy(games = pair.second)
)
itemDataList[index] = newItemData
}
itemDataList
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ dataList -> postResultList(dataList, list) }, {})
}
@SuppressLint("CheckResult")
private fun updateAdConfigAndDecorateList(itemDataList: ArrayList<SearchItemData>, list: MutableList<GameEntity>) {
mGameSearchAdList =
AdDelegateHelper.getGameSearchAdList().filter { AdDelegateHelper.shouldShowGameSearchAd(it) }.toArrayList()
.apply { sortBy { it.position } }
@ -137,7 +186,6 @@ class SearchGameResultViewModel(
mAdPositionSet = adPositionSet
if (adPositionSet.isNotEmpty()) {
val decoratedItemDataList = ArrayList(itemDataList)
val ownerAdList = arrayListOf<AdConfig>()
val thirdPartyAdList = arrayListOf<AdConfig>()
@ -175,18 +223,18 @@ class SearchGameResultViewModel(
Single.zip(requestSingleList) {}
.compose(singleToMain())
.subscribe({
decorateListWithAd(itemDataList, decoratedItemDataList, list, cpmSubjectEntity)
decorateListWithAd(itemDataList, list)
}, {
decorateListWithAd(itemDataList, decoratedItemDataList, list, cpmSubjectEntity)
decorateListWithAd(itemDataList, list)
})
} else {
decorateListWithAd(itemDataList, decoratedItemDataList, list, cpmSubjectEntity)
decorateListWithAd(itemDataList, list)
}
} else {
decorateListWithThirdPartyAdOnly(decoratedItemDataList, thirdPartyAdList, list, cpmSubjectEntity)
decorateListWithThirdPartyAdOnly(itemDataList, thirdPartyAdList, list)
}
} else {
decorateWithWGameSubjectCPM(itemDataList, list, cpmSubjectEntity)
postResultList(itemDataList, list)
}
}
@ -197,27 +245,25 @@ class SearchGameResultViewModel(
}
private fun decorateListWithThirdPartyAdOnly(
decoratedItemDataList: ArrayList<SearchItemData>,
itemDataList: ArrayList<SearchItemData>,
thirdPartyAdList: List<AdConfig>,
list: List<GameEntity>,
cpmSubjectEntity: SearchSubjectEntity?
list: List<GameEntity>
) {
thirdPartyAdList.forEach {
decoratedItemDataList.add(it.position - 1, SearchItemData(ad = it.thirdPartyAd, adConfig = it))
itemDataList.add(it.position - 1, SearchItemData(ad = it.thirdPartyAd, adConfig = it))
SPUtils.setLong(Constants.SP_LAST_GAME_SEARCH_AD_SHOW_TIME + it.position, System.currentTimeMillis())
}
decorateWithWGameSubjectCPM(decoratedItemDataList, list, cpmSubjectEntity)
postResultList(itemDataList, list)
}
private fun decorateListWithAd(
itemDataList: ArrayList<SearchItemData>,
decoratedItemDataList: ArrayList<SearchItemData>,
list: List<GameEntity>,
cpmSubjectEntity: SearchSubjectEntity?
list: List<GameEntity>
) {
val adGameOneIdSet = HashSet<String>() // 展示样式为单个游戏时记录游戏ID避免重复
val decoratedItemDataSize = itemDataList.size
for ((index, position) in mAdPositionSet!!.withIndex()) {
if (position < itemDataList.size + index + 1) {
if (position < decoratedItemDataSize + index + 1) {
val adConfig = mGameSearchAdList!!.safelyGetInRelease(index)
val showThirdPartyAd = adConfig?.displayRule?.adSource == AdDelegateHelper.AD_TYPE_SDK
val showOwnerAd = adConfig?.displayRule?.adSource == AdDelegateHelper.AD_TYPE_OWNER
@ -225,7 +271,7 @@ class SearchGameResultViewModel(
if ((showThirdPartyAd && adConfig?.thirdPartyAd != null)
|| (showOwnerAd && adConfig?.ownerAd == null && adConfig?.thirdPartyAd != null && showOnFailed)
) {
decoratedItemDataList.add(position - 1, SearchItemData(ad = adConfig.thirdPartyAd, adConfig = adConfig))
itemDataList.add(position - 1, SearchItemData(ad = adConfig.thirdPartyAd, adConfig = adConfig))
SPUtils.setLong(
Constants.SP_LAST_GAME_SEARCH_AD_SHOW_TIME + adConfig.position,
System.currentTimeMillis()
@ -237,7 +283,7 @@ class SearchGameResultViewModel(
if (!gameList.isNullOrEmpty()) {
if (adConfig.ownerAd.adSource?.displayStyle == "game_zone") {
// 游戏专题
decoratedItemDataList.add(
itemDataList.add(
position - 1,
SearchItemData(
subject = SearchSubjectEntity(
@ -259,7 +305,7 @@ class SearchGameResultViewModel(
}
randomGameEntity?.id?.let { adGameOneIdSet.add(it) }
decoratedItemDataList.add(
itemDataList.add(
position - 1,
SearchItemData(game = randomGameEntity, adConfig = adConfig)
)
@ -270,7 +316,7 @@ class SearchGameResultViewModel(
)
} else if (showOnFailed && adConfig.thirdPartyAd != null) {
// 自有广告为空时,显示第三方广告
decoratedItemDataList.add(position - 1, SearchItemData(ad = adConfig.thirdPartyAd, adConfig = adConfig))
itemDataList.add(position - 1, SearchItemData(ad = adConfig.thirdPartyAd, adConfig = adConfig))
SPUtils.setLong(
Constants.SP_LAST_GAME_SEARCH_AD_SHOW_TIME + adConfig.position,
System.currentTimeMillis()
@ -281,41 +327,7 @@ class SearchGameResultViewModel(
break
}
}
decorateWithWGameSubjectCPM(decoratedItemDataList, list, cpmSubjectEntity)
}
@SuppressLint("CheckResult")
private fun decorateWithWGameSubjectCPM(
resultList: ArrayList<SearchItemData>,
list: List<GameEntity>,
cpmSubjectEntity: SearchSubjectEntity?
) {
// 微信小游戏CPM专题搜索结果存在则请求CPM接口获取微信小游戏列表数据并将列表数据插入缓存的CPM专题中
// 再根据location的值固定为4将CPM专题插入搜索结果列表中
// 相关需求https://jira.shanqu.cc/browse/GHZSCY-6710
cpmSubjectEntity?.let { subject ->
if (subject.games.isNotEmpty()) {
Single.just(subject.games.toMutableList())
} else {
repository.getWGameCPMGameList()
.onErrorReturnItem(mutableListOf())
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
val cpmSearchItemData = SearchItemData(subject = subject.apply { games = it })
if (subject.location <= 0 || subject.location > resultList.size) {
resultList.add(cpmSearchItemData)
} else {
resultList.add(subject.location - 1, cpmSearchItemData)
}
postResultList(resultList, list)
},
{
postResultList(resultList, list)
})
} ?: postResultList(resultList, list)
postResultList(itemDataList, list)
}
@SuppressLint("CheckResult")
@ -343,7 +355,7 @@ class SearchGameResultViewModel(
}
private fun postResultList(resultList: ArrayList<SearchItemData>, list: List<GameEntity>) {
mResultLiveData.postValue(resultList)
mResultLiveData.postValue(resultList.toMutableList())
if (mPage == 1) {
if (repository is MiniGameSearchResultRepository) {
SensorsBridge.trackMiniGameSearchResultReturn(
@ -362,7 +374,6 @@ class SearchGameResultViewModel(
mSearchKey ?: "",
SearchActivity.toTrackSearchType(mSearchType),
list.isNotEmpty()
)
}
@ -431,7 +442,6 @@ class SearchGameResultViewModel(
companion object {
const val AD_SUBJECT_GAME_MAX_COUNT = 8
const val WGAME_CPM_SUBJECT_POSITION = 4
}
}

View File

@ -13,6 +13,8 @@ import com.lightgame.adapter.BaseRecyclerAdapter
class SearchSubjectAdapter(
context: Context,
private val mList: List<GameEntity>,
private val mColumnId: String,
private val mColumnName: String,
private val mEntrance: String,
private val mKey: String,
private val clickCallback: ((GameEntity) -> Unit)
@ -40,7 +42,10 @@ class SearchSubjectAdapter(
MiniGameItemHelper.launchMiniGame(gameEntity)
MiniGameItemHelper.trackMiniGameClick(
gameEntity = gameEntity,
gameColumnId = mColumnId,
gameColumnName = mColumnName,
location = "小游戏搜索结果列表",
position = position,
searchContent = mKey,
)
} else {

View File

@ -9,6 +9,7 @@ import com.gh.gamecenter.common.baselist.LoadStatus
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.clearHtmlFormatCompletely
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.home.custom.model.CustomPageData
import com.gh.gamecenter.livedata.Event
@ -141,7 +142,7 @@ class SearchGameListViewModel : ViewModel() {
SearchActivity.toTrackSearchType(type),
location,
collection.id,
collection.title
collection.title.clearHtmlFormatCompletely()
)
}
}

View File

@ -102,6 +102,7 @@ abstract class BaseTabWrapperFragment : BaseLazyFragment(), IMultiTab {
noDataStub = mCachedView.findViewById(R.id.reuse_no_data_stub)
noConnectionStub = mCachedView.findViewById(R.id.reuse_no_connection_stub)
loadingStub = mCachedView.findViewById(R.id.reuse_loading_stub)
showLoading(true)
backgroundColor = com.gh.gamecenter.common.R.color.ui_background.toColor(requireContext())
backgroundWhiteColor = com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext())

View File

@ -43,6 +43,8 @@ import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.eventbus.EBReuse
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.json.json
import com.gh.gamecenter.common.observer.MuteCallback
import com.gh.gamecenter.common.observer.VolumeObserver
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.view.TabIndicatorView
import com.gh.gamecenter.core.iinterface.IScrollable
@ -61,6 +63,7 @@ import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.exposure.time.TimeUtil
import com.gh.gamecenter.feature.game.GameItemViewHolder
import com.gh.gamecenter.feature.utils.SentryHelper
import com.gh.gamecenter.gamecollection.square.GameCollectionSquareFragment
import com.gh.gamecenter.home.custom.CustomPageFragment
import com.gh.gamecenter.home.video.AutomaticVideoView
@ -162,6 +165,20 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
private val twoLinesTabToolbarHeight = 48F.dip2px()
private var autoVideoView: AutomaticVideoView? = null
private val volumeObserver by lazy {
VolumeObserver(object : MuteCallback {
override fun onMute(isMute: Boolean) {
if (::binding.isInitialized) {
binding.muteIv.setImageResource(if (isMute) R.drawable.ic_basic_offsound else R.drawable.ic_basic_onsound)
}
if (isMute) {
autoVideoView?.mute()
} else {
autoVideoView?.unMute()
}
}
})
}
private var searchStyle: BottomTab.SearchStyle? = null
set(value) {
@ -214,7 +231,16 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = FragmentSearchToolbarTabWrapperBinding.inflate(layoutInflater)
binding = try {
FragmentSearchToolbarTabWrapperBinding.inflate(layoutInflater)
} catch (e: Exception) {
SentryHelper.onEvent("VIEW_BINDING_BIND_ERROR",
"digest", e.localizedMessage,
"gid", HaloApp.getInstance().gid
)
// 玄学,重试一次,该闪退闪退
FragmentSearchToolbarTabWrapperBinding.inflate(layoutInflater)
}
mCachedView = binding.root
return mCachedView
}
@ -557,6 +583,8 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
oldState: RefreshState,
newState: RefreshState
) {
getValidSmartRefreshContent()?.onStateChanged(refreshLayout, oldState, newState)
val isAutoScrollToTwoLevel = oldState == RefreshState.None && newState == RefreshState.TwoLevel
val isDragToTwoLevel =
oldState == RefreshState.ReleaseToRefresh && newState == RefreshState.ReleaseToTwoLevel
@ -654,49 +682,17 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
if (isFinishTwoLevel) {
pausePullDownPushVideo()
showTwoLevel = false
if (isDragging) {
autoFinishTwoLevelHandler?.removeMessages(KEY_AUTO_FINISH_TWO_LEVEL)
elapsedHelper.pauseCounting()
pullDownPush?.run {
SensorsBridge.trackEvent(
"DropDownPushClick",
json {
"action" to pullDownPushAction
"button_name" to "关闭推送"
"drop_down_push_id" to id
"game_name" to game?.name
"game_id" to game?.id
"bottom_tab" to bottomTabName
"several_tab_page_name" to multiTabNavName
"several_tab_page_id" to multiTabNavId
"position" to lastSelectedPosition
"tab_content" to currentTabEntity?.name
"custom_page_name" to currentTabEntity?.link?.text
"custom_page_id" to currentTabEntity?.link?.link
}
)
com.gh.common.util.NewFlatLogUtils.logHomePushClose(
id,
"主动收起",
twoLevelOpenCount,
game?.id ?: "",
game?.name ?: "",
elapsedHelper.elapsedTime
)
}
finishTwoLevel("主动收起")
}
showTwoLevel = false
}
when (newState) {
RefreshState.TwoLevel -> {
getValidSmartRefreshContent()?.setScrollEnabled(false)
binding.refreshLayout.isDisableContent = false
}
RefreshState.None -> {
getValidSmartRefreshContent()?.setScrollEnabled(true)
showTwoLevel = false
isDragging = false
twoLevelHeader.setFloorDuration(1000)
@ -940,6 +936,7 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
classicsHeader.visibility = View.INVISIBLE
pullDownPushSet.add(id)
SPUtils.setStringSet(Constants.SP_PULL_DOWN_PUSH_POP_UP_SET, pullDownPushSet)
autoFinishTwoLevelCallback = finishCallback
autoFinishTwoLevelHandler = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
@ -961,9 +958,6 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
val autoFinishDelayTime = putAwaySwitch.toInt() * 1000L
autoFinishTwoLevelHandler?.sendEmptyMessageDelayed(KEY_AUTO_FINISH_TWO_LEVEL, autoFinishDelayTime)
}
else -> {
autoFinishTwoLevelCallback = finishCallback
}
}
}
}
@ -971,6 +965,8 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
}
override fun setPullDownPush(pullDownPush: PullDownPush?, pullDownPushHandler: PullDownPushHandler?) {
if (!isAdded) return
if (autoVideoView == null) {
binding.autoVideoViewStub.setOnInflateListener { _, inflated ->
autoVideoView = LayoutAutoVideoViewBinding.bind(inflated).root
@ -1038,6 +1034,7 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
ImageUtils.display(gameImageIv, imgUrl)
}
autoVideoView?.onVideoReset()
muteIv.isVisible = video != null
autoVideoView?.goneIf(video == null) {
if (autoVideoView?.isInPlayingState == false) {
GSYVideoOptionBuilder()
@ -1056,6 +1053,17 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
headerContainer.performClick()
}
}
var videoVoiceStatus = SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
muteIv.setImageResource(if (videoVoiceStatus) R.drawable.ic_basic_offsound else R.drawable.ic_basic_onsound)
muteIv.setDebouncedClickListener {
videoVoiceStatus = !videoVoiceStatus
muteIv.setImageResource(if (videoVoiceStatus) R.drawable.ic_basic_offsound else R.drawable.ic_basic_onsound)
if (videoVoiceStatus) {
autoVideoView?.mute()
} else {
autoVideoView?.unMute()
}
}
}
}
}
@ -1070,6 +1078,19 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
pullDownPushHandler?.doPreProcess(this as? ISmartRefresh, popupPush)
}
private fun observeVolume() {
context?.applicationContext?.contentResolver?.registerContentObserver(
android.provider.Settings.System.CONTENT_URI,
true,
volumeObserver
)
}
private fun unObserveVolume() {
context?.applicationContext?.contentResolver?.unregisterContentObserver(volumeObserver)
}
private fun updateRefreshHeaderStyle(force: Boolean = false) {
if (lightRefreshHeaderStyle == isDisplayingLightContent && !force) return
lightRefreshHeaderStyle = isDisplayingLightContent
@ -1114,6 +1135,7 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
} else {
resumePullDownPushVideo()
}
observeVolume()
}
}
}
@ -1127,6 +1149,7 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
if (!videoUrl.isNullOrEmpty()) {
ScrollCalculatorHelper.savePlaySchedule(MD5Utils.getContentMD5(videoUrl), currentPosition)
}
unObserveVolume()
}
}
}
@ -1142,8 +1165,7 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
if (position != 0L) {
autoVideoView?.seekTo(position)
autoVideoView?.onVideoResume(false)
val topVideoVoiceStatus = SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
if (topVideoVoiceStatus) {
if (autoVideoView?.isMute == true) {
autoVideoView?.mute()
} else {
autoVideoView?.unMute()

View File

@ -21,6 +21,8 @@ import com.gh.gamecenter.entity.MultiTabNav
import com.gh.gamecenter.entity.PullDownPush
import com.gh.gamecenter.feature.utils.SentryHelper
import com.google.android.material.tabs.TabLayout
import com.scwang.smartrefresh.layout.api.RefreshLayout
import com.scwang.smartrefresh.layout.constant.RefreshState
import kotlin.math.roundToInt
/**
@ -148,10 +150,6 @@ class TabWrapperFragment: BaseTabWrapperFragment(), ISmartRefresh, ISmartRefresh
}
}
override fun setScrollEnabled(isScrollEnabled: Boolean) {
getValidSmartRefreshContent()?.setScrollEnabled(isScrollEnabled)
}
override fun onRefresh() {
getValidSmartRefreshContent()?.onRefresh()
}
@ -161,6 +159,10 @@ class TabWrapperFragment: BaseTabWrapperFragment(), ISmartRefresh, ISmartRefresh
getCurrentTabEntity()?.showPullDownPush = !isSwipeRefreshEnabled
}
override fun onStateChanged(refreshLayout: RefreshLayout, oldState: RefreshState, newState: RefreshState) {
getValidSmartRefreshContent()?.onStateChanged(refreshLayout, oldState, newState)
}
override fun setSmartRefreshEnabled(isEnable: Boolean) {
(parentFragment as? ISmartRefresh)?.setSmartRefreshEnabled(isEnable)
}

View File

@ -41,6 +41,8 @@ import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.eventbus.EBReuse
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.json.json
import com.gh.gamecenter.common.observer.MuteCallback
import com.gh.gamecenter.common.observer.VolumeObserver
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.MD5Utils
@ -108,6 +110,20 @@ class ToolbarWrapperFragment : LazyFragment(), ToolbarController, ISmartRefresh,
private var mLightToolbar = false
private var mAutoFinishTwoLevelHandler: Handler? = null
private var mAutoFinishTwoLevelCallback: (() -> Unit)? = null
private val mVolumeObserver by lazy {
VolumeObserver(object : MuteCallback {
override fun onMute(isMute: Boolean) {
if (::mBinding.isInitialized) {
mBinding.muteIv.setImageResource(if (isMute) R.drawable.ic_basic_offsound else R.drawable.ic_basic_onsound)
if (isMute) {
mBinding.autoVideoView.mute()
} else {
mBinding.autoVideoView.unMute()
}
}
}
})
}
private lateinit var mElapsedHelper: TimeElapsedHelper
@ -227,6 +243,7 @@ class ToolbarWrapperFragment : LazyFragment(), ToolbarController, ISmartRefresh,
gameImageIv.goneIf(video != null) {
ImageUtils.display(gameImageIv, imgUrl)
}
muteIv.isVisible = video != null
autoVideoView.goneIf(video == null) {
if (!autoVideoView.isInPlayingState) {
GSYVideoOptionBuilder()
@ -258,6 +275,17 @@ class ToolbarWrapperFragment : LazyFragment(), ToolbarController, ISmartRefresh,
headerContainer.performClick()
}
}
var videoVoiceStatus = SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
muteIv.setImageResource(if (videoVoiceStatus) R.drawable.ic_basic_offsound else R.drawable.ic_basic_onsound)
muteIv.setDebouncedClickListener {
videoVoiceStatus = !videoVoiceStatus
muteIv.setImageResource(if (videoVoiceStatus) R.drawable.ic_basic_offsound else R.drawable.ic_basic_onsound)
if (videoVoiceStatus) {
autoVideoView.mute()
} else {
autoVideoView.unMute()
}
}
}
}
}
@ -271,6 +299,18 @@ class ToolbarWrapperFragment : LazyFragment(), ToolbarController, ISmartRefresh,
pullDownPushHandler?.doPreProcess(this as? ISmartRefresh, popupPush)
}
private fun observeVolume() {
context?.applicationContext?.contentResolver?.registerContentObserver(
android.provider.Settings.System.CONTENT_URI,
true,
mVolumeObserver
)
}
private fun unObserveVolume() {
context?.applicationContext?.contentResolver?.unregisterContentObserver(mVolumeObserver)
}
override fun onFragmentPause() {
super.onFragmentPause()
DownloadManager.getInstance().removeObserver(mDataWatcher)
@ -434,6 +474,8 @@ class ToolbarWrapperFragment : LazyFragment(), ToolbarController, ISmartRefresh,
oldState: RefreshState,
newState: RefreshState
) {
(mContentFragment as? ISmartRefreshContent)?.onStateChanged(refreshLayout, oldState, newState)
val isAutoScrollToTwoLevel = oldState == RefreshState.None && newState == RefreshState.TwoLevel
val isDragToTwoLevel =
oldState == RefreshState.ReleaseToRefresh && newState == RefreshState.ReleaseToTwoLevel
@ -550,12 +592,9 @@ class ToolbarWrapperFragment : LazyFragment(), ToolbarController, ISmartRefresh,
when (newState) {
RefreshState.TwoLevel -> {
(mContentFragment as? ISmartRefreshContent)?.setScrollEnabled(false)
mBinding.refreshLayout.isDisableContent = false
}
RefreshState.None -> {
(mContentFragment as? ISmartRefreshContent)?.setScrollEnabled(true)
mShowTwoLevel = false
mIsDragging = false
twoLevelHeader.setFloorDuration(1000)
@ -739,6 +778,7 @@ class ToolbarWrapperFragment : LazyFragment(), ToolbarController, ISmartRefresh,
} else {
resumePullDownPushVideo()
}
observeVolume()
}
}
}
@ -752,6 +792,7 @@ class ToolbarWrapperFragment : LazyFragment(), ToolbarController, ISmartRefresh,
if (videoUrl.isNotEmpty()) {
ScrollCalculatorHelper.savePlaySchedule(MD5Utils.getContentMD5(videoUrl), currentPosition)
}
unObserveVolume()
}
}
}
@ -767,8 +808,7 @@ class ToolbarWrapperFragment : LazyFragment(), ToolbarController, ISmartRefresh,
if (position != 0L) {
autoVideoView.seekTo(position)
autoVideoView.onVideoResume(false)
val topVideoVoiceStatus = SPUtils.getBoolean(Constants.SP_VIDEO_PLAY_MUTE, true)
if (topVideoVoiceStatus) {
if (autoVideoView.isMute) {
autoVideoView.mute()
} else {
autoVideoView.unMute()

View File

@ -17,6 +17,7 @@ import com.gh.gamecenter.R
import com.gh.gamecenter.common.utils.ImageUtils
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.common.utils.layoutInflater
import com.gh.gamecenter.common.utils.safelyGetInRelease
import com.gh.gamecenter.common.view.PageControllerAdapter
import com.gh.gamecenter.common.view.PageTransformerAdapter
import com.gh.gamecenter.common.view.ScrollEventListener
@ -151,7 +152,8 @@ class VGameInstalledLaunchDialog : DialogFragment() {
launch.setOnClickListener { view ->
val currentItem = pageControllerAdapter.currentItem
val installedGame = installAdapter.currentList[currentItem]
val installedGame =
installAdapter.currentList.safelyGetInRelease(currentItem) ?: return@setOnClickListener
val vDownloadEntity =
VHelper.getVDownloadEntitySnapshot(installedGame.gameId, installedGame.packageName)
?: return@setOnClickListener

View File

@ -25,7 +25,6 @@ import com.facebook.imagepipeline.core.ImageTranscoderType;
import com.facebook.imagepipeline.core.MemoryChunkType;
import com.facebook.imagepipeline.decoder.ImageDecoderConfig;
import com.gh.ad.AdDelegateHelper;
import com.gh.ad.AdPluginDownloadHelper;
import com.gh.base.GlobalActivityLifecycleObserver;
import com.gh.common.FixedRateJobHelper;
import com.gh.common.filter.RegionSettingHelper;
@ -57,7 +56,6 @@ import com.gh.gamecenter.common.utils.DeviceUtils;
import com.gh.gamecenter.common.utils.EnvHelper;
import com.gh.gamecenter.common.utils.ExtensionsKt;
import com.gh.gamecenter.common.utils.ImageUtils;
import com.gh.gamecenter.common.utils.SensorsBridge;
import com.gh.gamecenter.core.AppExecutor;
import com.gh.gamecenter.core.iinterface.IApplication;
import com.gh.gamecenter.core.provider.IFlavorProvider;
@ -331,7 +329,8 @@ public class HaloApp extends MultiDexApplication {
OAIDHelper.INSTANCE.getOAID(HaloApp.this, (s, isSuccess) -> {
setOAID(s);
MetaUtil.INSTANCE.refreshMeta();
SensorsBridge.INSTANCE.setOAID(s);
DataUtils.bindValidOaidToSensor(true);
if (getGid() != null) {
DataUtils.getDeviceCertification(getGid());

View File

@ -0,0 +1,19 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M11.183,5.778C11.51,5.511 12,5.744 12,6.165V8.909C12,9.461 12.448,9.909 13,9.909C13.552,9.909 14,9.461 14,8.909V6.165C14,4.056 11.549,2.895 9.917,4.23L8.756,5.181C8.328,5.53 8.265,6.16 8.615,6.588C8.965,7.015 9.595,7.078 10.022,6.728L11.183,5.778Z"
android:fillColor="#000000"/>
<path
android:pathData="M20.66,7C20.384,6.522 19.772,6.358 19.294,6.634C18.816,6.91 18.652,7.522 18.928,8C19.63,9.216 20,10.596 20,12C20,12.92 19.841,13.83 19.534,14.69C19.349,15.21 19.62,15.782 20.14,15.968C20.66,16.153 21.232,15.882 21.418,15.362C21.802,14.287 22,13.15 22,12C22,10.245 21.538,8.52 20.66,7Z"
android:fillColor="#000000"/>
<path
android:pathData="M17.796,10.447C17.653,9.914 17.104,9.597 16.571,9.74C16.037,9.883 15.721,10.431 15.864,10.965C15.967,11.35 16.012,11.748 15.998,12.143C15.978,12.695 16.409,13.159 16.961,13.179C17.513,13.198 17.976,12.767 17.996,12.215C18.017,11.622 17.951,11.026 17.796,10.447Z"
android:fillColor="#000000"/>
<path
android:pathData="M2.224,4.869C2.572,4.441 3.202,4.376 3.631,4.724L19.631,17.724C20.059,18.072 20.124,18.702 19.776,19.131C19.428,19.559 18.798,19.624 18.369,19.276L14,15.726V17.835C14,19.944 11.549,21.105 9.917,19.77L7.143,17.5H5C3.343,17.5 2,16.157 2,14.5V9.5C2,8.476 2.513,7.571 3.297,7.03L2.369,6.276C1.941,5.928 1.876,5.298 2.224,4.869ZM5.106,8.5L12,14.101V17.835C12,18.256 11.51,18.489 11.183,18.222L8.133,15.726C7.955,15.58 7.731,15.5 7.5,15.5H5C4.448,15.5 4,15.052 4,14.5V9.5C4,8.948 4.448,8.5 5,8.5H5.106Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
</vector>

View File

@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M9.917,4.23C11.549,2.895 14,4.056 14,6.165V17.835C14,19.944 11.549,21.105 9.917,19.77L7.143,17.5H5C3.343,17.5 2,16.157 2,14.5V9.5C2,7.843 3.343,6.5 5,6.5H7.143L9.917,4.23ZM12,6.165C12,5.744 11.51,5.511 11.183,5.778L8.133,8.274C7.955,8.42 7.731,8.5 7.5,8.5H5C4.448,8.5 4,8.948 4,9.5V14.5C4,15.052 4.448,15.5 5,15.5H7.5C7.731,15.5 7.955,15.58 8.133,15.726L11.183,18.222C11.51,18.489 12,18.257 12,17.835V6.165Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
<path
android:pathData="M16.571,9.74C17.104,9.597 17.653,9.914 17.796,10.447C18.068,11.464 18.068,12.536 17.796,13.553C17.653,14.086 17.104,14.403 16.571,14.26C16.037,14.117 15.721,13.569 15.864,13.035C16.045,12.357 16.045,11.643 15.864,10.965C15.721,10.431 16.037,9.883 16.571,9.74Z"
android:fillColor="#000000"/>
<path
android:pathData="M20.66,7C20.384,6.522 19.772,6.358 19.294,6.634C18.816,6.91 18.652,7.522 18.928,8C19.63,9.216 20,10.596 20,12C20,13.404 19.63,14.784 18.928,16C18.652,16.478 18.816,17.09 19.294,17.366C19.772,17.642 20.384,17.478 20.66,17C21.538,15.48 22,13.755 22,12C22,10.245 21.538,8.52 20.66,7Z"
android:fillColor="#000000"/>
</vector>

View File

@ -164,6 +164,19 @@
app:lottie_loop="true"
app:lottie_repeatMode="restart" />
<ImageView
android:id="@+id/muteIv"
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="24dp"
android:padding="4dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="@drawable/ic_basic_offsound"
app:tint="@color/text_instance" />
<FrameLayout
android:id="@+id/headerBackground"
android:layout_width="0dp"

View File

@ -169,6 +169,19 @@
app:lottie_loop="true"
app:lottie_repeatMode="restart" />
<ImageView
android:id="@+id/muteIv"
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="24dp"
android:padding="4dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="@drawable/ic_basic_offsound"
app:tint="@color/text_instance" />
<View
android:id="@+id/headerBackground"
android:layout_width="0dp"

View File

@ -1,5 +1,6 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/reuseSearchBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/ui_surface"

View File

@ -10,6 +10,7 @@
android:id="@+id/cv_banner_container"
android:layout_width="0dp"
android:layout_height="0dp"
app:cardBackgroundColor="@color/transparent"
app:cardCornerRadius="8dp"
app:cardElevation="0dp"
app:layout_constraintDimensionRatio="41:11"

View File

@ -7,8 +7,8 @@ ext {
targetSdkVersion = 30
// application info (每个大版本之间的 versionCode 增加 20)
versionCode = 1112
versionName = "5.38.2"
versionCode = 1116
versionName = "5.38.6"
applicationId = "com.gh.gamecenter"
applicationIdGat = "com.gh.gamecenter.intl"
@ -143,7 +143,7 @@ ext {
acloudPush = "3.8.8.1"
jpushVersion = "5.4.0"
jverifiationVersion = "3.1.7"
jverifiationVersion = "3.2.5"
honorPushVersion = "7.0.61.303"
volcTlsVersion = "1.1.4"

View File

@ -27,7 +27,6 @@ import com.gh.gamecenter.feedback.view.suggest.SuggestionActivity
import com.gh.gamecenter.floatingwindow.R
import com.gh.gamecenter.floatingwindow.databinding.DialogQaFeedbackBinding
import com.lightgame.dialog.BaseDialogFragment
import org.bouncycastle.asn1.x500.style.RFC4519Style.title
import org.greenrobot.eventbus.EventBus
class QaFeedbackDialogFragment : BaseDialogFragment() {

View File

@ -39,7 +39,7 @@ object JPushHelper {
// 绑定ID关系
@SuppressLint("CheckResult")
fun bindRegistrationId(registrationId: String?) {
SensorsBridge.profileAppend(KEY_REGISTRATION_ID, registrationId ?: "")
// SensorsBridge.profileSet(KEY_REGISTRATION_ID, registrationId ?: "")
val appProvider = ARouter.getInstance().build(RouteConsts.provider.app).navigation() as? IAppProvider
val data = mapOf(

View File

@ -79,6 +79,7 @@ public class Constants {
public static final String QQ_MINI_GAME = "qq";
public static final String WECHAT_MINI_GAME = "wechat";
public static final String WECHAT_MINI_GAME_CPM = "wechat_cpm";
public static final String WECHAT_MINI_GAME_PROFIT_CPM = "CPM";
/**
* <a href="https://developers.weixin.qq.com/community/minigame/doc/000c461a17c6486f0641e27176b401">微信小游戏PCS参数</a>
*/
@ -473,6 +474,10 @@ public class Constants {
public static final String SP_BRAND_NEW_FIRST_LAUNCH_TIME = "brand_new_first_launch_time"; // 全新安装用户首次启动时间
public static final String INVALID_OAID_1 = "00000000-0000-0000-0000-000000000000";
public static final String INVALID_OAID_2 = "0000000000000000000000000000000000000000000000000000000000000000";
public static final String INVALID_OAID_3 = "00000000000000000000000000000000";
public static final String IS_RESERVE_ONLINE_REMINDER = "is_reserve_online_reminder";
public static final String TOOL_MAP_PACKAGE_NAME = "com.gh.toolmap";// 光环工具服务APP包名

View File

@ -37,7 +37,7 @@ data class ExposureEntity(
@SerializedName("mini_game_type")
val miniGameType: String? = "",// 小游戏类型QQ小游戏qq 微信小游戏wechat
@SerializedName("mini_game_recommend_id")
val miniGameRecommendId: String? = "",
var miniGameRecommendId: String? = null,
var speed: Long = 0,
var certification: Int? = null, // 0表示未实名1表示未成年2表示成年

View File

@ -67,7 +67,6 @@ import io.reactivex.SingleTransformer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
@ -455,6 +454,17 @@ fun String.containHtmlTag(): Boolean {
return matcher.find()
}
fun String.dropFontColorInDarkMode(context: Context) : String {
return if (DarkModeUtils.isDarkModeOn(context)) {
val fontColorRegex = Pattern.compile("<font[^>]*color[^>]*>")
val matcher = fontColorRegex.matcher(this)
return matcher.replaceAll("")
} else {
this
}
}
/**
* 用户行为相关
*/
@ -1405,11 +1415,13 @@ fun WebView.enableForceDark(isDarkModeOn: Boolean) {
false
}
if (isFeatureSupported) {
WebSettingsCompat.setForceDark(
settings,
if (isDarkModeOn) WebSettingsCompat.FORCE_DARK_ON else WebSettingsCompat.FORCE_DARK_OFF
)
DarkModeUtils.isWebViewForceDarkEnabled = isDarkModeOn
tryWithDefaultCatch {
WebSettingsCompat.setForceDark(
settings,
if (isDarkModeOn) WebSettingsCompat.FORCE_DARK_ON else WebSettingsCompat.FORCE_DARK_OFF
)
DarkModeUtils.isWebViewForceDarkEnabled = isDarkModeOn
}
}
}

View File

@ -328,7 +328,7 @@ object SensorsBridge {
}
fun setOAID(oaid: String) {
if (mIsSensorsEnabled) mSensor?.setOAID(oaid)
if (mIsSensorsEnabled || oaid.isNotEmpty()) mSensor?.setOAID(oaid)
}
@JvmStatic

View File

@ -284,17 +284,20 @@ data class GameEntity(
@SerializedName("message_private_id")
var messageId: String = "",
// 小游戏服务商ID目前仅用于微信小游戏CPM
// 小游戏用户ID目前仅用于微信小游戏CPM对应着小游戏的appid字段
@SerializedName("wxappid")
var miniGameUid: String = "",
// 小游戏ID仅用于小游戏
// 如果是微信小游戏则对应着小游戏的user_name字段
// 如果是QQ小游戏则对应着小游戏的game_id字段
@SerializedName("appid")
var miniGameAppId: String = "",
// 小游戏状态(1下架 2秒玩),仅用于小游戏
@SerializedName("app_status")
var miniGameAppStatus: Int = 0,
// 小游戏类qq/wechat/wechat_cpm),仅用于小游戏
// 小游戏类qq/wechat仅用于小游戏
@SerializedName("game_type")
var miniGameType: String = "",
var miniGameCategory: String = "",
// 小游戏链接URL仅用于小游戏
@SerializedName("appidLink")
var miniGameAppLink: String = "",
@ -308,10 +311,13 @@ data class GameEntity(
var usage: Int = 0,
// 游戏封面图,仅用于微信小游戏
var banner: String = "",
// 收益来源(CPM),仅用于微信小游戏
var profit: String = "",
// 宣传图,仅用于微信小游戏
@SerializedName("publicity_img")
var publicityImg: List<String>? = null,
// 小游戏在搜索结果的位置仅用于微信小游戏CPM搜索结果列表
var location: Int = -1,
@SerializedName("first_setting")
var firstSetting: FirstSetting? = null,
@SerializedName("bubble_text")
@ -797,6 +803,11 @@ data class GameEntity(
return category.equals("gjonline")
}
val miniGameType: String get() = when(profit) {
Constants.WECHAT_MINI_GAME_PROFIT_CPM -> Constants.WECHAT_MINI_GAME_CPM
else -> miniGameCategory
}
/**
* 当前游戏是否为小游戏
*/
@ -1061,7 +1072,7 @@ data class GameEntity(
val showImage: Boolean
get() {
if (!DISPLAY_CONTENT_IMAGE.equals(displayContent, true)) {
if (!DISPLAY_CONTENT_IMAGE.equals(displayContent, true) && topVideo != null) {
return false
}
return (isWechatMiniGame() && banner.isNotBlank()) || homeSetting.image.isNotBlank()

View File

@ -115,7 +115,7 @@ data class ExposureEvent(
miniGameUid = gameEntity?.miniGameUid ?: "",
miniGameId = gameEntity?.miniGameAppId ?: "",
miniGameType = gameEntity?.miniGameType ?: "",
miniGameRecommendId = gameEntity?.miniGameRecommendId ?: "",
miniGameRecommendId = gameEntity?.miniGameRecommendId,
additional = gameEntity?.customPageTrackData?.toKV()
)
this.id = UUID.randomUUID().toString()

View File

@ -109,12 +109,7 @@ object MiniGameItemHelper {
gameName = gameEntity.name ?: ""
)
if (gameEntity.miniGameType == Constants.WECHAT_MINI_GAME_CPM) {
WGameSubjectCPMListReportHelper.reportClick(
miniAppUid = gameEntity.miniGameUid,
gameName = gameEntity.name ?: "",
operateTime = System.currentTimeMillis() / 1000,
recommendId = gameEntity.miniGameRecommendId
)
WGameSubjectCPMListReportHelper.reportClick(gameEntity)
}
}
}

View File

@ -7,6 +7,7 @@ import com.gh.gamecenter.common.utils.EnvHelper
import com.gh.gamecenter.common.utils.FixedSizeLinkedHashSet
import com.gh.gamecenter.common.utils.toRequestBody
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.WXMiniGameCPMResponse
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.retrofit.RetrofitManager
@ -22,7 +23,38 @@ object WGameSubjectCPMListReportHelper {
private val exposureRequestSet by lazy { hashSetOf<String>() }
private val exposureCacheSet by lazy { FixedSizeLinkedHashSet<String>(100) }
/**
* recommendId为空正在调用CPM接口的点击事件集合
*/
private val pendingRecommendIdClickSet by lazy { hashSetOf<WGSubjectPendingClick>() }
fun reportClick(
gameEntity: GameEntity,
operateTime: Long = System.currentTimeMillis() / 1000
) {
val recommendId = gameEntity.miniGameRecommendId.ifEmpty {
gameEntity.exposureEvent?.payload?.miniGameRecommendId // 如果游戏实体的recommendId为空则取它绑定的曝光事件的recommendId
} ?: return
if (recommendId.isNotEmpty()) {
reportClickInner(
miniAppUid = gameEntity.miniGameUid,
gameName = gameEntity.name ?: "",
operateTime = System.currentTimeMillis() / 1000,
recommendId = recommendId
)
return
}
// 没有曝光事件的点击事件上报是不合理的
val exposureEvent = gameEntity.exposureEvent ?: return
// 正在调用接口请求获取recommendId需要等待recommendId回调以后再执行上报
pendingRecommendIdClickSet.add(WGSubjectPendingClick(operateTime, exposureEvent))
Utils.log(
"WXGameCPMReport",
"当前微信CPM小游戏正在请求CPM接口获取RecommendId将延迟到RecommendId获取后上报${gameEntity.name}, ${gameEntity.miniGameAppId}"
)
}
private fun reportClickInner(
miniAppUid: String,
gameName: String,
operateTime: Long,
@ -78,6 +110,69 @@ object WGameSubjectCPMListReportHelper {
}
fun reportExposure(exposure: ExposureEvent) {
val recommendId = exposure.payload.miniGameRecommendId ?: return
if (recommendId.isEmpty()) {// recommendId为空时需要请求CPM接口获取recommendId的值
requestRecommendIdAndReportExposure(exposure)
} else {
reportExposureInner(exposure)
}
}
/**
* 先请求CPM接口获取RecommendId再提交曝光事件
*/
@SuppressLint("CheckResult")
private fun requestRecommendIdAndReportExposure(exposure: ExposureEvent) {
val wxappid = exposure.payload.miniGameUid!!
val meta = MetaUtil.getMeta()
val request = mapOf(
"head" to mapOf(
"busiAppid" to EnvHelper.getWGameCPMBusiAppId(),
"oaid" to (meta.oaid ?: ""),
"manufacturer" to (meta.manufacturer ?: ""),
"mode" to (meta.model ?: ""),
"androidId" to (MetaUtil.getAndroidId()),
"imei" to (MetaUtil.getIMEI())
),
"body" to mapOf(
"appIDList" to listOf(wxappid)
)
)
Utils.log(
"WXGameCPMReport",
"请求CPM接口获取RecommendId${exposure.payload.gameName}"
)
RetrofitManager.getInstance()
.wGameCPMApiService
.getGameInfoList(request.toRequestBody())
.subscribe({
if (it.ret == 0 && it.appInfoList.isNotEmpty()) {
exposure.payload.miniGameRecommendId = it.appInfoList[0].recommendID
Utils.log(
"WXGameCPMReport",
"请求CPM接口获取RecommendId成功${exposure.payload.gameName}, ${exposure.payload.miniGameRecommendId}"
)
reportExposureInner(exposure)// 上报曝光事件
pendingRecommendIdClickSet.forEach { click ->
if (click.exposure === exposure) {// 上报延迟的点击事件
reportClickInner(
miniAppUid = exposure.payload.miniGameUid ?: "",
gameName = exposure.payload.gameName ?: "",
operateTime = click.operateTime,
recommendId = exposure.payload.miniGameRecommendId!!
)
}
}
}
pendingRecommendIdClickSet.removeAll {
click -> click.exposure === exposure }
}, {
pendingRecommendIdClickSet.removeAll {
click -> click.exposure === exposure }
})
}
private fun reportExposureInner(exposure: ExposureEvent) {
val recommendId = exposure.payload.miniGameRecommendId ?: return
val gameName = exposure.payload.gameName ?: ""
if (exposureCacheSet.contains(recommendId)) {
@ -173,4 +268,9 @@ object WGameSubjectCPMListReportHelper {
val posCard: Int = 0,
val posInCard: Int = 0
)
class WGSubjectPendingClick(
val operateTime: Long,
val exposure: ExposureEvent
)
}

View File

@ -9,6 +9,9 @@ import retrofit2.http.POST
interface WGameCPMApiService {
@POST("geteditorrecommend")
fun getEditorRecommendList(@Body body: RequestBody): Single<WXMiniGameCPMEntity>
@POST("getuserrecommend")
fun getUserRecommendList(@Body body: RequestBody): Single<WXMiniGameCPMEntity>
@ -18,4 +21,7 @@ interface WGameCPMApiService {
@POST("reportexposure")
fun reportExposure(@Body body: RequestBody): Single<WXMiniGameCPMResponse>
@POST("getgameinfolist")
fun getGameInfoList(@Body body: RequestBody): Single<WXMiniGameCPMEntity>
}

View File

@ -97,6 +97,8 @@ public class WXEntryActivity extends Activity implements IWXAPIEventHandler, WeC
&& !((SendAuth.Resp) baseResp).state.contains("qqminigame")
) {
WXAPIProxyFactory.getLiveData().postValue(baseResp);
} else if (baseResp.getType() == ConstantsAPI.COMMAND_SUBSCRIBE_MESSAGE) {
WXAPIProxyFactory.getLiveData().postValue(baseResp);
}
String resultString = "";

View File

@ -3,32 +3,50 @@ package com.gh.gamecenter.va
import android.app.Application
import android.content.Context
import android.content.res.Configuration
import android.os.Build
import com.gh.gamecenter.core.iinterface.IApplication
import com.google.auto.service.AutoService
import com.lg.vspace.common.CommonApp
import com.lg.vspace.App64
@AutoService(IApplication::class)
class HaloApp : IApplication {
private val commonApp = CommonApp()
private val app = App64()
private val isDeviceSupportVa = Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1
override fun attachBaseContext(base: Context) {
commonApp.attachBaseContext(base)
if (isDeviceSupportVa) {
app.attachBaseContext(base)
}
}
override fun onCreate(application: Application) {
commonApp.onCreate(application)
if (isDeviceSupportVa) {
app.onCreate(application)
}
}
override fun onLowMemory() {
if (isDeviceSupportVa) {
app.onLowMemory()
}
}
override fun onTerminate() {
if (isDeviceSupportVa) {
app.onTerminate()
}
}
override fun onTrimMemory(level: Int) {
if (isDeviceSupportVa) {
app.onTrimMemory(level)
}
}
override fun onConfigurationChanged(newConfig: Configuration) {
if (isDeviceSupportVa) {
app.onConfigurationChanged(newConfig)
}
}
}

View File

@ -9,13 +9,6 @@ build_time_without_divider=$(TZ=Asia/Shanghai date +'%Y%m%d%H%M')L
post_init_script=init.internal.gradle
# 开启 mapping 上传
if [[ "$OSTYPE" == "darwin"* ]]; then
sed -i '' '1 a plugins { id "io.sentry.android.gradle" version "3.7.0" } ' app/build.gradle
else
sed -i '1 a plugins { id "io.sentry.android.gradle" version "3.7.0" }' app/build.gradle
fi
git checkout module_common/build.gradle
git checkout gradle.properties

2
vasdk

Submodule vasdk updated: 270ed85b7d...0a83d50210