Compare commits

..

59 Commits

Author SHA1 Message Date
5de629cfdd feat: 更新插件1.0.3 正式版本 url 2024-10-17 15:42:59 +08:00
f026623600 Merge branch 'refactor/sync-va' into 'dev'
chore: va组件升级到2.0.6

See merge request halo/android/assistant-android!1937
2024-10-17 11:24:35 +08:00
2f5ee0eb91 chore: va组件升级到2.0.6
refactor: update commit id
2024-10-17 11:24:12 +08:00
e7651e8092 Merge branch 'feat/GHZSCY-6708-patch' into 'dev'
feat: CPM微信小游戏API接入兼容OkHttp 4.x

See merge request halo/android/assistant-android!1936
2024-10-17 11:23:47 +08:00
82d51d6375 feat: CPM微信小游戏API接入兼容OkHttp 4.x 2024-10-17 11:23:24 +08:00
6080edfd8a Merge branch 'feat/GHZSCY-6708' into 'dev'
feat: CPM微信小游戏API接入工作—客户端 https://jira.shanqu.cc/browse/GHZSCY-6708

See merge request halo/android/assistant-android!1911
2024-10-17 10:17:19 +08:00
d9713571c9 feat: CPM微信小游戏API接入工作—客户端 https://jira.shanqu.cc/browse/GHZSCY-6708 2024-10-17 10:17:19 +08:00
b466525e8b Merge branch 'feat/GHZSCY-6790' into 'dev'
feat: 更新 OkHttp 至 4.X 最新版本并启用 brotli 压缩 https://jira.shanqu.cc/browse/GHZSCY-6790

See merge request halo/android/assistant-android!1935
2024-10-16 16:56:07 +08:00
2a25675dce feat: 更新 OkHttp 至 4.X 最新版本并启用 brotli 压缩 https://jira.shanqu.cc/browse/GHZSCY-6790 2024-10-16 16:56:06 +08:00
5486ad8818 Merge branch 'fix/home_appbar_style' into 'dev'
fix: 修复多tab导航页在无Tab样式下AppBar变色异常的问题

See merge request halo/android/assistant-android!1934
2024-10-16 13:47:17 +08:00
5552fcf7bc Merge branch 'fix/stop_banner_play_on_pause' into 'dev'
fix: 修复部分轮播图没有在页面暂停时停止播放的问题

See merge request halo/android/assistant-android!1933
2024-10-16 13:47:10 +08:00
782a0af13c fix: 修复多tab导航页在无Tab样式下AppBar变色异常的问题 2024-10-16 11:44:44 +08:00
c6c2d9cd12 fix: 修复部分轮播图没有在页面暂停时停止播放的问题 2024-10-16 10:09:51 +08:00
f929a08e46 Merge branch 'fix/GHZSCY-6685' into 'dev'
fix: 修复 Fresco 不能根据 ViewPager/ViewPager2 页面可见性变更动图播放状态的问题 https://jira.shanqu.cc/browse/GHZSCY-6685

See merge request halo/android/assistant-android!1930
2024-10-15 18:16:41 +08:00
e48f96d7d7 fix: 修复 Fresco 不能根据 ViewPager/ViewPager2 页面可见性变更动图播放状态的问题 https://jira.shanqu.cc/browse/GHZSCY-6685 2024-10-15 18:16:41 +08:00
3cc95dbc08 Merge branch 'fix/system-properties-sensitive' into 'dev'
fix: 修复xcrash敏感行为【读取系统属性】

See merge request halo/android/assistant-android!1929
2024-10-15 15:08:29 +08:00
f75396d7ae fix: 修复xcrash敏感行为【读取系统属性】 2024-10-15 15:07:57 +08:00
72c3df7fa6 Merge branch 'fix/GHZSCY-6773' into 'dev'
fix:【光环助手】游戏专题-右上角显示问题 https://jira.shanqu.cc/browse/GHZSCY-6773

See merge request halo/android/assistant-android!1928
2024-10-15 09:35:38 +08:00
2d4920cfb0 fix:【光环助手】游戏专题-右上角显示问题 https://jira.shanqu.cc/browse/GHZSCY-6773 2024-10-15 09:31:13 +08:00
2d30b97cca Merge branch 'fix/hiddenapibypass-bug' into 'dev'
fix: 更新hiddenapibypass库,观察native crash的hiddenapi相关问题是否解决。

See merge request halo/android/assistant-android!1927
2024-10-14 17:09:30 +08:00
40346e3c9a fix: 更新hiddenapibypass库,观察native crash的hiddenapi相关问题是否解决。 2024-10-14 17:08:20 +08:00
7f601c856a Merge branch 'fix/illegal_state_exception' into 'dev'
fix: 尝试修复游戏专题合集详情页闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/388936

See merge request halo/android/assistant-android!1924
2024-10-12 11:36:49 +08:00
6e56f2e3a0 fix: 尝试修复游戏专题合集详情页闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/388936 2024-10-12 10:40:26 +08:00
e2fbda1e4c Merge branch 'fix/GHZSCY-6778' into 'dev'
fix: 分类页面展示异常 https://jira.shanqu.cc/browse/GHZSCY-6778

See merge request halo/android/assistant-android!1921
2024-10-11 16:45:57 +08:00
1e88ba8539 fix: 分类页面展示异常 https://jira.shanqu.cc/browse/GHZSCY-6778 2024-10-11 15:40:03 +08:00
0f43b5610d Merge branch 'feat/GHZSCY-6474' into 'dev'
feat: 【光环助手】搜索榜单的神策埋点问题 https://jira.shanqu.cc/browse/GHZSCY-6747

See merge request halo/android/assistant-android!1920
2024-10-11 15:10:51 +08:00
04dcfbab2e feat: 【光环助手】搜索榜单的神策埋点问题 https://jira.shanqu.cc/browse/GHZSCY-6747 2024-10-11 15:10:51 +08:00
8dd33cb599 Merge branch 'fix/GHZSCY-6777' into 'dev'
fix: 【光环助手】进入QA详情页埋点上报问题 https://jira.shanqu.cc/browse/GHZSCY-6777

See merge request halo/android/assistant-android!1917
2024-10-11 15:02:10 +08:00
af5826962b fix: 【光环助手】进入QA详情页埋点上报问题 https://jira.shanqu.cc/browse/GHZSCY-6777 2024-10-11 15:02:10 +08:00
9883f8d5c0 Merge branch 'fix/GHZSCY-6772' into 'dev'
fix: 分流器-验收问题-客户端 https://jira.shanqu.cc/browse/GHZSCY-6772

See merge request halo/android/assistant-android!1918
2024-10-11 15:01:59 +08:00
848207784e fix: 分流器-验收问题-客户端 https://jira.shanqu.cc/browse/GHZSCY-6772 2024-10-11 15:01:59 +08:00
fc294f9e7b Merge branch 'revert/GHZSCY-5572' into 'dev'
Revert: 搜索业务-新增搜索发现取代热门标签—客户端 https://jira.shanqu.cc/browse/GHZSCY-5572

See merge request halo/android/assistant-android!1916
2024-10-09 17:00:42 +08:00
96cd53a2c9 Revert: 搜索业务-新增搜索发现取代热门标签—客户端 https://jira.shanqu.cc/browse/GHZSCY-5572 2024-10-09 17:00:42 +08:00
5458c93475 fix: 处理合并冲突
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2024-10-09 15:53:40 +08:00
675d63c1d6 Merge remote-tracking branch 'origin/release' into dev
# Conflicts:
#	.gitlab-ci.yml
#	app/src/main/java/com/gh/gamecenter/download/DownloadFragment.kt
#	dependencies.gradle
#	vasdk
2024-10-09 15:34:08 +08:00
1040f5ff4d Merge branch 'sentry/407275' into 'release'
fix: Sentry 407275 修复Z10机型报BadTokenException的异常

See merge request halo/android/assistant-android!1915
2024-10-09 14:56:18 +08:00
97be320529 fix: Sentry 407275 修复Z10机型报BadTokenException的异常 2024-10-09 14:56:18 +08:00
0e086c9452 Merge branch 'fix/va-some-npe' into 'dev'
fix: 修复sentry捕获异常。

See merge request halo/android/assistant-android!1914
2024-10-09 14:13:09 +08:00
dc677d1b9f fix: 修复sentry捕获异常。
1.https://sentry.shanqu.cc/organizations/lightgame/issues/396947/?project=22
2.https://sentry.shanqu.cc/organizations/lightgame/issues/398572/events/0d99a320eee243efa7089b59cb10219c/?project=22
3.https://sentry.shanqu.cc/organizations/lightgame/issues/382462/events/30a62c7d5e0a40df80f36ff25b325728/?project=22
4.https://sentry.shanqu.cc/organizations/lightgame/issues/407819/?project=22
5.https://sentry.shanqu.cc/organizations/lightgame/issues/397248/?project=22
2024-10-09 14:10:54 +08:00
fa50c6e417 Merge branch 'fix/crashes' into 'dev'
修复Sentry闪退问题

See merge request halo/android/assistant-android!1913
2024-10-09 14:04:48 +08:00
dc96f2274f fix: 修复启动时QQ小游戏获取WebView的默认UserAgent导致的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/352547/?project=22 2024-10-09 11:32:36 +08:00
ad5f5048a6 Merge branch 'fix/auto-login-crash' into 'dev'
fix:自动登录页面闪退

See merge request halo/android/assistant-android!1912
2024-10-09 11:20:24 +08:00
e5491fb297 fix:自动登录页面闪退 2024-10-09 11:20:24 +08:00
ff96eaafee fix: 修复获取统计数据时出现的空指针闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/387745/?project=22 2024-10-08 17:33:43 +08:00
59cde4e2bf Merge branch 'hotfix/v5.37.5-1095/privacy-policy' into 'release'
feat: 优化获取进程名的方式 https://jira.shanqu.cc/browse/GHZSCY-6690

See merge request halo/android/assistant-android!1898
2024-09-20 10:56:40 +08:00
cc0c7c7fae feat: 优化获取进程名的方式 https://jira.shanqu.cc/browse/GHZSCY-6690 2024-09-20 10:32:29 +08:00
9e9ce6a84f Merge branch 'hotfix/v5.37.5-1095/download_ad_crash' into 'release'
fix: 修复下载管理展示第三方广告失败回落展示自有广告时出现的闪退问题...

See merge request halo/android/assistant-android!1895
2024-09-14 17:23:26 +08:00
7d0b500ff9 fix: 修复下载管理展示第三方广告失败回落展示自有广告时出现的闪退问题 https://sentry.shanqu.cc/organizations/lightgame/issues/409586/?project=22 2024-09-14 17:13:23 +08:00
425456b263 Merge branch 'feat/v5.37.5-1095/va-2.0.5' into 'release'
Feat/v5.37.5 1095/va 2.0.5

See merge request halo/android/assistant-android!1890
2024-09-11 17:08:07 +08:00
f6abab9a2d Revert "chore: 组件升级 2.0.5-debug" 2024-09-11 17:05:56 +08:00
d194f969e4 chore: va组件2.0.5-debug 2024-09-10 16:43:57 +08:00
95f66344fb chore: va组件2.0.5 2024-09-10 13:46:15 +08:00
570e2fa9bc Revert "feat:同步商业版代码至:dbc3b8ecaca3e774b1e63f41e70b651f4acfaee1"
This reverts commit 811d42457c.
2024-09-05 15:22:32 +08:00
9e07080043 feat: 调整依赖源顺序 2024-09-04 17:03:37 +08:00
e10a329159 chore: 版本更新至 5.37.5 2024-09-04 16:00:00 +08:00
b3bc7b43f7 Merge branch 'feat/v5.37.5-1095/update-va' into 'release'
feat:同步商业版代码至:dbc3b8ecaca3e774b1e63f41e70b651f4acfaee1

See merge request halo/android/assistant-android!1875
2024-09-04 15:54:34 +08:00
811d42457c feat:同步商业版代码至:dbc3b8ecaca3e774b1e63f41e70b651f4acfaee1 2024-09-04 15:52:46 +08:00
ac0b819ea9 Merge branch 'feat/GHZSCY-6644' into 'release'
feat: 【光环助手】安装相关优化功能埋点事件的属性字段英文错误的问题 https://jira.shanqu.cc/browse/GHZSCY-6644

See merge request halo/android/assistant-android!1874
2024-09-04 15:43:47 +08:00
d931fb5940 feat: 【光环助手】安装相关优化功能埋点事件的属性字段英文错误的问题 https://jira.shanqu.cc/browse/GHZSCY-6644 2024-09-04 14:42:17 +08:00
92 changed files with 689 additions and 327 deletions

View File

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

View File

@ -65,7 +65,7 @@ public class InstallUtils {
if (!TextUtils.isEmpty(installVersion) && downloadEntity != null &&
installVersion.equals(downloadEntity.getVersionName())) {
if (!downloadEntity.isPluggable() || PackageUtils.isSignedByGh(context, packageName)) {
EventBus.getDefault().post(new EBPackage(EBPackage.TYPE_INSTALLED, packageName, installVersion));
EventBus.getDefault().post(new EBPackage(EBPackage.TYPE_INSTALLED, packageName, installVersion, false));
}
}
}
@ -82,7 +82,7 @@ public class InstallUtils {
keys.add(packageName);
} else if (!list.contains(packageName)) {
keys.add(packageName);
EventBus.getDefault().post(new EBPackage("卸载", packageName, ""));
EventBus.getDefault().post(new EBPackage("卸载", packageName, "", false));
}
}
for (String key : keys) {

View File

@ -27,7 +27,9 @@ import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody
import org.json.JSONArray
import org.json.JSONObject
@ -124,11 +126,12 @@ object UsageStatsHelper {
&& curEvent.className == nextEvent.className
) {
val diff = nextEvent.timeStamp - curEvent.timeStamp
val packageName = curEvent.packageName ?: continue
if (pakAndTime[curEvent.packageName] == null) {
pakAndTime[curEvent.packageName] = diff
if (pakAndTime[packageName] == null) {
pakAndTime[packageName] = diff
} else {
pakAndTime[curEvent.packageName] = pakAndTime[curEvent.packageName]!! + diff
pakAndTime[packageName] = pakAndTime[packageName]!! + diff
}
}
}
@ -175,7 +178,7 @@ object UsageStatsHelper {
return
}
val body = RequestBody.create(MediaType.parse("application/json"), postBody.toString())
val body = postBody.toString().toRequestBody("application/json".toMediaTypeOrNull())
mApi.postUsageStatus(body, UserManager.getInstance().userId)
.subscribe(object : BiResponse<ResponseBody>() {
override fun onSuccess(data: ResponseBody) {

View File

@ -34,7 +34,9 @@ import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONException
import org.json.JSONObject
import java.util.*
@ -216,7 +218,7 @@ object PackageObserver {
try {
jsonObject.put("game_id", gameId)
jsonObject.put("package", packageName)
val rBody = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
val rBody = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
RetrofitManager.getInstance().api
.postPlayedGame(UserManager.getInstance().userId, rBody)
.subscribeOn(Schedulers.io())

View File

@ -94,8 +94,8 @@ object ExoCacheManager {
response =
OkHttpClient.Builder().connectTimeout(5, TimeUnit.SECONDS).readTimeout(5, TimeUnit.SECONDS).build()
.newCall(request).execute()
if (response!!.isSuccessful && response.body() != null) {
val length = response.body()!!.contentLength()
if (response!!.isSuccessful && response.body != null) {
val length = response.body!!.contentLength()
contentLength = if (length == 0L) -1L else length
}
} catch (e: Exception) {

View File

@ -238,7 +238,7 @@ open class SearchActivity : BaseActivity() {
GlobalActivityManager.getCurrentPageEntity().pageId,
GlobalActivityManager.getCurrentPageEntity().pageName,
key ?: "",
TRACK_SEARCH_TYPE_DEFAULT,
TRACK_SEARCH_TYPE_RANK,
mSourceEntrance
)
}
@ -433,12 +433,14 @@ open class SearchActivity : BaseActivity() {
const val TRACK_SEARCH_TYPE_INPUT = "输入搜索"
const val TRACK_SEARCH_TYPE_DEFAULT = "默认搜索"
const val TRACK_SEARCH_TYPE_HISTORY = "历史搜索"
const val TRACK_SEARCH_TYPE_RANK = "榜单搜索"
@JvmStatic
fun toTrackSearchType(type: String) = when (type) {
SearchType.AUTO.value -> TRACK_SEARCH_TYPE_AUTO
SearchType.MANUAL.value -> TRACK_SEARCH_TYPE_INPUT
SearchType.HISTORY.value -> TRACK_SEARCH_TYPE_HISTORY
SearchType.RANK.value -> TRACK_SEARCH_TYPE_RANK
else -> TRACK_SEARCH_TYPE_DEFAULT
}

View File

@ -32,7 +32,7 @@ class AmwaySearchDefaultFragment : SearchDefaultFragment() {
mViewModel.playedGames.observeNonNull(viewLifecycleOwner) {
defaultViewModel?.isExistHotSearch = it.isNotEmpty()
updateView()
mBinding.searchDiscoveryList.run {
mBinding.hotList.run {
layoutManager = LinearLayoutManager(context)
adapter = AmwaySearchAdapter(context, mViewModel, "安利墙搜索-最近玩过").apply { setData(it) }
}
@ -43,7 +43,7 @@ class AmwaySearchDefaultFragment : SearchDefaultFragment() {
override fun initView() {
mBinding = mAmwayBinding.searchContent
mBinding.searchDiscoveryHeadContainer.headTitle.text = "最近玩过"
mBinding.hotHeadContainer.headTitle.text = "最近玩过"
mBinding.historyFlexContainer.setLimitHeight(mFlexMaxHeight)
updateHistorySearchView(null)

View File

@ -309,7 +309,8 @@ class CategoryV2ListFragment : ListFragment<GameEntity, CategoryV2ListViewModel>
// 安装/卸载 事件
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(busFour: EBPackage) {
if (busFour.isInstalledOrUninstalled()) {
// 忽略首次初始化触发的事件
if (!busFour.fromInit && busFour.isInstalledOrUninstalled()) {
mAdapter?.notifyDataSetChanged()
}
}

View File

@ -27,7 +27,7 @@ open class BaseCloudArchiveViewModel(application: Application, private val mConf
)
.enqueue(object : Callback {
override fun onResponse(call: Call, response: Response) {
mArchiveConfigStr = response.body()?.string() ?: ""
mArchiveConfigStr = response.body?.string() ?: ""
callback?.invoke(mArchiveConfigStr)
}

View File

@ -161,6 +161,7 @@ class DownloadFragment : BaseFragment_TabLayout() {
val showOnFailed = downloadManagerAd?.displayRule?.onFailedAction == "show"
if ((showThirdPartyAd && thirdPartyAd != null) || (!showThirdPartyAd && thirdPartyAd != null && ownerAd == null)) {
initThirdPartyAd(downloadManagerAd, thirdPartyAd) { isSuccess ->
if (!isAdded) return@initThirdPartyAd
mBinding.maskView.goneIf(!isSuccess)
if (!isSuccess && ownerAd != null && showOnFailed) {
mSlideInterval = ownerAd.adSource?.sliderInterval ?: -1
@ -215,7 +216,7 @@ class DownloadFragment : BaseFragment_TabLayout() {
}
private fun initOwnerAd(adConfig: AdConfig) {
if (adConfig.id.isEmpty()) return
if (!isAdded || adConfig.id.isEmpty()) return
mAdGameViewModel = viewModelProvider(AdGameViewModel.Factory(adConfig))
initAdGameBanner(adConfig)
mBinding.closeAdIv.setOnClickListener {
@ -249,6 +250,7 @@ class DownloadFragment : BaseFragment_TabLayout() {
adConfig.displayRule.onFailedAction == "show" && adConfig.thirdPartyAd != null) {
// 自有广告游戏为空时,显示第三方广告
initThirdPartyAd(adConfig, adConfig.thirdPartyAd) { isSuccess ->
if (!isAdded) return@initThirdPartyAd
mBinding.maskView.goneIf(!isSuccess)
if (isSuccess) {
SPUtils.setLong(Constants.SP_LAST_DOWNLOAD_MANAGER_AD_SHOW_TIME, System.currentTimeMillis())

View File

@ -220,7 +220,7 @@ class NewInstalledGameFragment : ToolbarFragment() {
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(packageEb: EBPackage) {
if (packageEb.isInstalledOrUninstalled()) {
if (!packageEb.fromInit && packageEb.isInstalledOrUninstalled()) {
mInstallGameViewModel.initData(
PackagesManager.filterSameApk(
PackagesManager.filterDownloadBlackPackage(mPackageViewModel?.getGameInstalledLiveData()?.value as MutableList<GameInstall>?)

View File

@ -1,6 +1,12 @@
package com.gh.gamecenter.eventbus
class EBPackage(var type: String, var packageName: String, var versionName: String?) {
/**
* @param fromInit 实体生成是否来自于初始化
*/
class EBPackage(var type: String,
var packageName: String,
var versionName: String?,
val fromInit: Boolean = false) {
var gameId: String? = null
var isVGame: Boolean = false // 是否是畅玩游戏

View File

@ -39,14 +39,14 @@ class ForumOrUserSearchDefaultFragment : SearchDefaultFragment() {
override fun initView() {
mBinding = FragmentSearchDefaultBinding.bind(mCachedView)
mBinding.searchDiscoveryTagHeadContainer.root.visibility = View.GONE
mBinding.searchDiscoveryTagFlexContainer.visibility = View.GONE
mBinding.hotTagHeadContainer.root.visibility = View.GONE
mBinding.hotTagFlexContainer.visibility = View.GONE
if (mEntrance == "论坛首页" || mEntrance == "搜索栏") {
mBinding.searchDiscoveryHeadContainer.headTitle.text = "热门论坛"
mBinding.hotHeadContainer.headTitle.text = "热门论坛"
mViewModel.getForumSearchHotContent()
} else {
mBinding.searchDiscoveryHeadContainer.root.visibility = View.GONE
mBinding.searchDiscoveryList.visibility = View.GONE
mBinding.hotHeadContainer.root.visibility = View.GONE
mBinding.hotList.visibility = View.GONE
}
val params = mBinding.historyHeadContainer.root.layoutParams as ConstraintLayout.LayoutParams
params.topMargin = 0.5f.dip2px()

View File

@ -67,6 +67,8 @@ class ColumnCollectionDetailFragment : LazyListFragment<LinkEntity, ColumnCollec
}
private fun showSubjectTab(linkEntityList: MutableList<LinkEntity>) {
if (!isVisible) return
val subjectDataList = arrayListOf<SubjectData>()
for (link in linkEntityList) {

View File

@ -45,7 +45,9 @@ import com.zhihu.matisse.Matisse
import com.zhihu.matisse.internal.utils.PathUtils
import io.reactivex.disposables.Disposable
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import java.io.File
import kotlin.collections.component1
import kotlin.collections.component2
@ -420,10 +422,8 @@ class GameUploadFragment : ToolbarFragment() {
requestMap["type"] = mGameType
}
val body = RequestBody.create(
MediaType.parse("application/json"),
GsonUtils.toJson(requestMap)
)
val body = GsonUtils.toJson(requestMap)
.toRequestBody("application/json".toMediaTypeOrNull())
mViewModel.uploadGames(body)
}

View File

@ -968,7 +968,7 @@ class GameCollectionDetailFragment :
// 安装/卸载 事件
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(busFour: EBPackage) {
if (busFour.isInstalledOrUninstalled()) {
if (!busFour.fromInit && busFour.isInstalledOrUninstalled()) {
if (EBPackage.TYPE_INSTALLED == busFour.type
&& UserManager.getInstance().isLoggedIn
&& (mEntity?.count?.playedGame ?: 0) < (mEntity?.count?.game ?: 0)

View File

@ -7,6 +7,9 @@ import android.os.Handler
import android.os.Looper
import android.os.Message
import android.view.animation.AccelerateDecelerateInterpolator
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.gh.common.util.DirectUtils
@ -21,6 +24,17 @@ class GameCollectionAmwayViewHolder(var binding: GameCollectionSquareAmwayItemBi
private val mAdapter = GameCollectionAmwayAdapter(binding.root.context)
private val mLooperHandle = LooperHandle(this)
private val mSlideLooperKey = 333
private val mLifecycleObserver = object : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
super.onResume(owner)
startAutoPlay()
}
override fun onPause(owner: LifecycleOwner) {
super.onPause(owner)
stopAutoPlay()
}
}
fun bindAmway(amwayList: List<AmwayCommentEntity>, viewModel: GameCollectionSquareViewModel) {
mAdapter.setAmwayList(amwayList)
@ -54,6 +68,14 @@ class GameCollectionAmwayViewHolder(var binding: GameCollectionSquareAmwayItemBi
mLooperHandle.removeMessages(mSlideLooperKey)
}
fun onViewAttach(lifecycle: Lifecycle) {
lifecycle.addObserver(mLifecycleObserver)
}
fun onViewDetach(lifecycle: Lifecycle) {
lifecycle.removeObserver(mLifecycleObserver)
}
fun ViewPager2.setCurrentItem(
item: Int,
duration: Long,

View File

@ -2,6 +2,7 @@ package com.gh.gamecenter.gamecollection.square
import android.content.Context
import android.view.ViewGroup
import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.exposure.ExposureManager
import com.gh.common.util.DirectUtils
@ -23,6 +24,7 @@ import com.lightgame.adapter.BaseRecyclerAdapter
class GameCollectionBannerAdapter(
context: Context,
private val mLifecycleOwner: LifecycleOwner,
private val mViewModel: GameCollectionSquareViewModel,
var mBannerList: List<CarouselEntity> = emptyList(),
private var mAmwayListItem: List<AmwayCommentEntity>? = null,
@ -78,6 +80,20 @@ class GameCollectionBannerAdapter(
return index
}
override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
super.onViewAttachedToWindow(holder)
if (holder is GameCollectionAmwayViewHolder) {
holder.onViewAttach(mLifecycleOwner.lifecycle)
}
}
override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
super.onViewDetachedFromWindow(holder)
if (holder is GameCollectionAmwayViewHolder) {
holder.onViewDetach(mLifecycleOwner.lifecycle)
}
}
companion object {
const val ITEM_AMWAY = 100
const val ITEM_BANNER = 101

View File

@ -12,6 +12,9 @@ import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.PagerSnapHelper
import androidx.recyclerview.widget.RecyclerView
@ -47,6 +50,7 @@ import java.lang.ref.WeakReference
class GameCollectionSquareAdapter(
context: Context,
private val mLifecycleOwner: LifecycleOwner,
private val mIsHome: Boolean = false,
private val mFragment: GameCollectionSquareFragment,
private val mViewModel: GameCollectionSquareViewModel,
@ -157,7 +161,7 @@ class GameCollectionSquareAdapter(
when (holder) {
is GameCollectionHeaderItemViewHolder -> {
val itemData = mEntityList[position]
holder.bindHeader(itemData, mBasicExposureSource, mViewModel)
holder.bindHeader(mLifecycleOwner, itemData, mBasicExposureSource, mViewModel)
}
is GameCollectionFilterItemViewHolder -> holder.bindFilter(mFragment, mViewModel, mRefreshCallback)
@ -211,6 +215,20 @@ class GameCollectionSquareAdapter(
override fun getItemCount() =
if (mEntityList.isNullOrEmpty()) 0 else if (mIsHome && mEntityList.size == 2) mEntityList.size else mEntityList.size + 1
override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
super.onViewAttachedToWindow(holder)
if (holder is GameCollectionHeaderItemViewHolder) {
holder.onViewAttach(mLifecycleOwner.lifecycle)
}
}
override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
super.onViewDetachedFromWindow(holder)
if (holder is GameCollectionHeaderItemViewHolder) {
holder.onViewDetach(mLifecycleOwner.lifecycle)
}
}
class GameCollectionHeaderItemViewHolder(val binding: ItemGameCollectionHeaderBinding) :
RecyclerView.ViewHolder(binding.root) {
private lateinit var mBannerAdapter: GameCollectionBannerAdapter
@ -218,8 +236,20 @@ class GameCollectionSquareAdapter(
private lateinit var mBannerLayoutManager: LinearLayoutManager
private val mLooperHandle = LooperHandle(this)
private val mSlideLooperKey = 111
private val mLifecycleObserver = object : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
super.onResume(owner)
startAutoPlay()
}
override fun onPause(owner: LifecycleOwner) {
super.onPause(owner)
stopAutoPlay()
}
}
fun bindHeader(
lifecycleOwner: LifecycleOwner,
itemData: GameCollectionListItemData,
mBasicExposureSource: List<ExposureSource>,
viewModel: GameCollectionSquareViewModel
@ -249,6 +279,7 @@ class GameCollectionSquareAdapter(
mBannerLayoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
mBannerAdapter = GameCollectionBannerAdapter(
context,
lifecycleOwner,
viewModel,
bannerList,
amwayListItem,
@ -345,6 +376,14 @@ class GameCollectionSquareAdapter(
mLooperHandle.removeMessages(mSlideLooperKey)
}
fun onViewAttach(lifecycle: Lifecycle) {
lifecycle.addObserver(mLifecycleObserver)
}
fun onViewDetach(lifecycle: Lifecycle) {
lifecycle.removeObserver(mLifecycleObserver)
}
class LooperHandle(viewHolder: GameCollectionHeaderItemViewHolder) : Handler(Looper.getMainLooper()) {
private val mWeakReference: WeakReference<GameCollectionHeaderItemViewHolder> = WeakReference(viewHolder)

View File

@ -138,6 +138,7 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
mGuideContainer?.visibility = View.GONE
} else {
if (mExposureEventList.isNotEmpty()) ExposureManager.log(mExposureEventList)
stopAutoPlay()
}
val stayTime = (System.currentTimeMillis() - startPageTime) / 1000
NewFlatLogUtils.logGameCollectSquareStayTime(stayTime, if (mUseAlternativeLayout) "首页tab栏" else "游戏单广场")
@ -175,6 +176,8 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
)
)
}
} else {
startAutoPlay()
}
mElapsedHelper.resetCounting()
mElapsedHelper.resumeCounting()
@ -270,6 +273,7 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
mAdapter =
GameCollectionSquareAdapter(
requireContext(),
viewLifecycleOwner,
mUseAlternativeLayout,
this,
mViewModel,
@ -382,6 +386,7 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
val bannerAdapter = GameCollectionBannerAdapter(
requireContext(),
viewLifecycleOwner,
mViewModel,
mEntrance = "游戏单广场",
mBasicExposureSource = mBasicExposureSourceList
@ -515,7 +520,8 @@ class GameCollectionSquareFragment : LazyListFragment<GamesCollectionEntity, Gam
}
private fun startAutoPlay() {
if ((mDefaultBinding.headerContainer.bannerRv.adapter as GameCollectionBannerAdapter).getActualSize() <= 1) return
val bannerAdapter = mDefaultBinding.headerContainer.bannerRv.adapter as? GameCollectionBannerAdapter
if (bannerAdapter == null || bannerAdapter.getActualSize() <= 1) return
stopAutoPlay()
mLooperHandle.sendEmptyMessageDelayed(mSlideLooperKey, BANNER_LOOP_TIME)
}

View File

@ -394,7 +394,7 @@ class SpecialDownloadDialogFragment : BaseDraggableDialogFragment() {
SensorsBridge.trackDownloadComponentsContentClick(
gameId = gameEntity.id,
gameName = gameEntity.name ?: "unknown",
gameSchemeType = gameEntity.gameBitChinese,
gameSchemaType = gameEntity.gameBitChinese,
downloadStatus = gameEntity.downloadStatusChinese,
gameType = gameEntity.categoryChinese,
downloadType = if (asVGame) "畅玩下载" else "本地下载",
@ -405,7 +405,7 @@ class SpecialDownloadDialogFragment : BaseDraggableDialogFragment() {
SensorsBridge.trackDownloadComponentsShow(
gameId = gameEntity.id,
gameName = gameEntity.name ?: "unknown",
gameSchemeType = gameEntity.gameBitChinese,
gameSchemaType = gameEntity.gameBitChinese,
downloadStatus = gameEntity.downloadStatusChinese,
gameType = gameEntity.categoryChinese,
downloadType = if (asVGame) "畅玩下载" else "本地下载",

View File

@ -45,7 +45,9 @@ import com.gh.gamecenter.login.user.UserManager
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONObject
import retrofit2.HttpException
@ -541,7 +543,7 @@ class RatingEditActivity : ToolBarActivity(), KeyboardHeightObserver {
jsonObject.put("rom", MetaUtil.getRom().name + " " + MetaUtil.getRom().versionName)
jsonObject.put("again", again)
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
CheckLoginUtils.checkLogin(this, mEntrance) {
mViewModel.postGameComment(mComment?.id ?: "", body)

View File

@ -140,7 +140,7 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
searchToolbarTabWrapperViewModel =
viewModelProviderFromParent(
SearchToolbarTabWrapperViewModel.Factory(multiTabNavId, noTabLinkId),
multiTabNavId
multiTabNavId + noTabLinkId
)
}
if (bottomTabId.isNotEmpty()) {

View File

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

View File

@ -123,8 +123,12 @@ abstract class BaseCustomViewHolder(
_title.name = subject.name
tvTitle.text = subject.name ?: ""
}
if (_title.rightText != subject.home) {
_title.rightText = subject.home
val home = subject.home ?: ""
val homeText = subject.homeText ?: ""
if (_title.rightHome != home || _title.rightText != homeText) {
_title.rightHome = home
_title.rightText = homeText
fun getHomeText(defaultResId: Int): String =
if (subject.homeText.isNullOrBlank()) {
defaultResId.toResString()
@ -363,6 +367,7 @@ abstract class BaseCustomViewHolder(
data class TitleData(
var name: String? = null,
var rightHome: String? = null,
var rightText: String? = null,
var isRefresh: Boolean = false,
var icon: String? = null,

View File

@ -13,7 +13,7 @@ object HeadUpDisplayLogHelper {
source = source,
downloadType = if (downloadEntity.asVGame()) "畅玩下载" else "本地下载",
downloadStatus = downloadEntity.getMetaExtra(Constants.DOWNLOAD_STATUS_IN_CHINESE),
gameSchemeType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位",
gameSchemaType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位",
gameType = downloadEntity.getMetaExtra(Constants.GAME_CATEGORY_IN_CHINESE),
gameId = downloadEntity.gameId,
gameName = downloadEntity.name
@ -25,7 +25,7 @@ object HeadUpDisplayLogHelper {
source = source,
downloadType = if (downloadEntity.asVGame()) "畅玩下载" else "本地下载",
downloadStatus = downloadEntity.getMetaExtra(Constants.DOWNLOAD_STATUS_IN_CHINESE),
gameSchemeType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位",
gameSchemaType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位",
gameType = downloadEntity.getMetaExtra(Constants.GAME_CATEGORY_IN_CHINESE),
gameId = downloadEntity.gameId,
gameName = downloadEntity.name
@ -36,7 +36,7 @@ object HeadUpDisplayLogHelper {
SensorsBridge.trackAutomaticInstallationPromptBarShow(
downloadType = if (downloadEntity.asVGame()) "畅玩下载" else "本地下载",
downloadStatus = downloadEntity.getMetaExtra(Constants.DOWNLOAD_STATUS_IN_CHINESE),
gameSchemeType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位",
gameSchemaType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位",
gameType = downloadEntity.getMetaExtra(Constants.GAME_CATEGORY_IN_CHINESE),
gameId = downloadEntity.gameId,
gameName = downloadEntity.name
@ -47,7 +47,7 @@ object HeadUpDisplayLogHelper {
SensorsBridge.trackAutomaticInstallationPromptBarClick(
downloadType = if (downloadEntity.asVGame()) "畅玩下载" else "本地下载",
downloadStatus = downloadEntity.getMetaExtra(Constants.DOWNLOAD_STATUS_IN_CHINESE),
gameSchemeType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位",
gameSchemaType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位",
gameType = downloadEntity.getMetaExtra(Constants.GAME_CATEGORY_IN_CHINESE),
gameId = downloadEntity.gameId,
gameName = downloadEntity.name

View File

@ -6,7 +6,9 @@ import com.gh.gamecenter.retrofit.service.ApiService
import com.gh.gamecenter.subject.ISubjectRepository
import io.reactivex.Observable
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.ResponseBody
import okhttp3.ResponseBody.Companion.toResponseBody
class QGameSubjectRepository(
private val api: ApiService = RetrofitManager.getInstance().newApi
@ -17,7 +19,7 @@ class QGameSubjectRepository(
}
override fun getSubjectName(column_id: String?): Observable<ResponseBody> {
return Observable.just(ResponseBody.create(MediaType.parse("application/json"), "{\"name\": \"专题\"}"))
return Observable.just("{\"name\": \"专题\"}".toResponseBody("application/json".toMediaTypeOrNull()))
}
}

View File

@ -14,7 +14,7 @@ class WGameSubjectCPMRemoteDataSource(
private val api: WGameCPMApiService = RetrofitManager.getInstance().wGameCPMApi
) {
fun getRecommendCPMList(page: Int, pageSize: Int = 20): Single<MutableList<GameEntity>> {
fun getRecommendCPMList(page: Int, pageSize: Int = 10): Single<MutableList<GameEntity>> {
val meta = MetaUtil.getMeta()
val request = mapOf(
"head" to mapOf(

View File

@ -4,7 +4,9 @@ import com.gh.gamecenter.entity.SubjectSettingEntity
import com.gh.gamecenter.subject.ISubjectRepository
import io.reactivex.Observable
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.ResponseBody
import okhttp3.ResponseBody.Companion.toResponseBody
class WGameSubjectCPMRepository : ISubjectRepository {
override fun getColumnSettings(column_id: String?): Observable<SubjectSettingEntity> {
@ -12,6 +14,6 @@ class WGameSubjectCPMRepository : ISubjectRepository {
}
override fun getSubjectName(column_id: String?): Observable<ResponseBody> {
return Observable.just(ResponseBody.create(MediaType.parse("application/json"), "{\"name\": \"专题\"}"))
return Observable.just("{\"name\": \"专题\"}".toResponseBody("application/json".toMediaTypeOrNull()))
}
}

View File

@ -6,7 +6,9 @@ import com.gh.gamecenter.retrofit.service.ApiService
import com.gh.gamecenter.subject.ISubjectRepository
import io.reactivex.Observable
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.ResponseBody
import okhttp3.ResponseBody.Companion.toResponseBody
class WGameSubjectRepository(
private val api: ApiService = RetrofitManager.getInstance().newApi
@ -16,6 +18,6 @@ class WGameSubjectRepository(
}
override fun getSubjectName(column_id: String?): Observable<ResponseBody> {
return Observable.just(ResponseBody.create(MediaType.parse("application/json"), "{\"name\": \"专题\"}"))
return Observable.just("{\"name\": \"专题\"}".toResponseBody("application/json".toMediaTypeOrNull()))
}
}

View File

@ -119,7 +119,8 @@ object PackageRepository {
packageKey = packageFilterManager.packageKey,
filteredList = filteredList,
isVGame = false,
updateInstallStatus = true
updateInstallStatus = true,
fromInit = true
)
}
},
@ -256,13 +257,15 @@ object PackageRepository {
* @param onWorkerThreadOnly 是否在工作线程执行
* @param isVGame 包名列表是否为畅玩游戏
* @param updateInstallStatus 更新安装状态 (通过 EventBus 来进行)
* @param fromInit 是否来自数据首次初始化
*/
@SuppressLint("CheckResult")
private fun loadInstalledGameDigestAndNotifyData(
packageKey: String,
filteredList: ArrayList<String>,
isVGame: Boolean = false,
updateInstallStatus: Boolean = false
updateInstallStatus: Boolean = false,
fromInit: Boolean = false
) {
var isNotifyUpdate = false
val maxPageCount = (filteredList.size / PAGE_SIZE) + 1
@ -291,7 +294,7 @@ object PackageRepository {
for (game in validGames) {
val shouldNotifyChanges =
validateGameAndPostChanges(gh_id, game, pkgName, isVGame, updateInstallStatus)
validateGameAndPostChanges(gh_id, game, pkgName, isVGame, updateInstallStatus, fromInit)
if (!isNotifyUpdate && shouldNotifyChanges) {
isNotifyUpdate = true
}
@ -317,7 +320,8 @@ object PackageRepository {
game: GameEntity,
pkgName: String,
isVGame: Boolean,
updateInstallStatus: Boolean
updateInstallStatus: Boolean,
fromInit: Boolean = false
): Boolean {
if (ghId == null || ghId == game.id) {
gameInstalled.add(GameInstall.transformGameInstall(game, pkgName, isVGame))
@ -328,7 +332,7 @@ object PackageRepository {
if (updateInstallStatus) {
EventBus.getDefault()
.post(EBPackage(EBPackage.TYPE_INSTALLED, pkgName, game.getApk().firstOrNull()?.version))
.post(EBPackage(EBPackage.TYPE_INSTALLED, pkgName, game.getApk().firstOrNull()?.version, fromInit))
}
if (isCanUpdate || isCanPluggable) {

View File

@ -374,12 +374,14 @@ class HaloPersonalFragment : BaseLazyFragment() {
}
mSuperiorChain?.registerInferiorChain(mPriorityChain)
startBannerAutoPlay()
}
override fun onFragmentPause() {
super.onFragmentPause()
mSuperiorChain?.unregisterInferiorChain(mPriorityChain)
stopBannerAutoPlay()
}
@SuppressLint("CheckResult", "SetTextI18n")
@ -1011,7 +1013,7 @@ class HaloPersonalFragment : BaseLazyFragment() {
}
private fun startBannerAutoPlay() {
if (mPersonalBannerAdapter.getActualSize() < 2) return
if (!::mPersonalBannerAdapter.isInitialized || mPersonalBannerAdapter.getActualSize() < 2) return
stopBannerAutoPlay()
mLooperHandle.sendEmptyMessageDelayed(mSlideLooperKey, BANNER_LOOP_TIME)
}

View File

@ -20,7 +20,9 @@ import com.gh.gamecenter.retrofit.RetrofitManager
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody
import org.json.JSONArray
import org.json.JSONObject
@ -75,7 +77,7 @@ class InstalledGameDialog(
jsonObject.put("package", game.packageName)
objects.put(jsonObject)
}
val requestBody = RequestBody.create(MediaType.parse("application/json"), objects.toString())
val requestBody = objects.toString().toRequestBody("application/json".toMediaTypeOrNull())
RetrofitManager.getInstance().api
.postPlayedGames(UserManager.getInstance().userId, requestBody)
.subscribeOn(Schedulers.io())

View File

@ -25,7 +25,9 @@ import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody
import org.greenrobot.eventbus.EventBus
import org.json.JSONObject
@ -259,10 +261,8 @@ class AnswerDetailViewModel(application: Application) : AndroidViewModel(applica
fun toggleComment(answerId: String, isCommentable: Boolean) {
val params = HashMap<String, Boolean>()
params["commentable"] = isCommentable
val body = RequestBody.create(
MediaType.parse("application/json"),
JSONObject(params as Map<*, *>).toString()
)
val body = JSONObject(params as Map<*, *>).toString()
.toRequestBody("application/json".toMediaTypeOrNull())
RetrofitManager.getInstance()
.api

View File

@ -26,7 +26,9 @@ import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody
import org.greenrobot.eventbus.EventBus
import org.json.JSONArray
@ -144,7 +146,7 @@ class ArticleEditViewModel(application: Application) : BaseRichEditorViewModel(a
if (draftEntity?.id != null) {
articleBody.put("draft_id", draftEntity?.id)
}
val body = RequestBody.create(MediaType.parse("application/json"), articleBody.toString())
val body = articleBody.toString().toRequestBody("application/json".toMediaTypeOrNull())
val observable = if (detailEntity == null) {
mApi.postCommunityArticle(mSelectCommunityData?.id, body)
} else {
@ -226,7 +228,7 @@ class ArticleEditViewModel(application: Application) : BaseRichEditorViewModel(a
if (mSelectCommunityData != null && mSelectCommunityData!!.id.isNotEmpty()) {
articleBody.put("community_id", mSelectCommunityData!!.id)
}
val body = RequestBody.create(MediaType.parse("application/json"), articleBody.toString())
val body = articleBody.toString().toRequestBody("application/json".toMediaTypeOrNull())
val observable = if (draftEntity?.id != null) {
mApi.patchCommunityArticleDrafts(UserManager.getInstance().userId, draftEntity?.id, body)
} else {

View File

@ -28,7 +28,9 @@ import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody
import org.greenrobot.eventbus.EventBus
import org.json.JSONArray
@ -266,7 +268,7 @@ class QuestionEditViewModel(application: Application) : BaseRichEditorViewModel(
}
processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true))
val body = RequestBody.create(MediaType.parse("application/json"), bodyJson)
val body = bodyJson.toRequestBody("application/json".toMediaTypeOrNull())
mApi.moderatorsPatchQuestion(body, UserManager.getInstance().userId, questionEntity?.id)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())

View File

@ -15,7 +15,9 @@ import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody
import org.json.JSONException
import org.json.JSONObject
@ -59,7 +61,7 @@ class QuestionsInviteViewModel(application: Application, var questionId: String?
e.printStackTrace()
}
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
RetrofitManager.getInstance().api
.postInvite(body, questionId)
.subscribeOn(Schedulers.io())

View File

@ -30,7 +30,9 @@ import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody
import org.json.JSONObject
import retrofit2.HttpException
@ -114,7 +116,7 @@ class VideoPublishViewModel(application: Application) : AndroidViewModel(applica
when {
isDraft -> {
val draftData = JSONObject(videoEntity.toJson()).put("local_path", videoPath).toString()
val body = RequestBody.create(MediaType.parse("application/json"), draftData)
val body = draftData.toRequestBody("application/json".toMediaTypeOrNull())
postDraft(body)
}
videoPatch != null -> {
@ -150,7 +152,7 @@ class VideoPublishViewModel(application: Application) : AndroidViewModel(applica
private fun patchVideo(jsonObject: JSONObject, videoId: String) {
processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true))
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
mApi.patchBbsVideo(videoId, body)
.compose(observableToMain())
.subscribe(object : Response<ResponseBody>() {
@ -208,7 +210,7 @@ class VideoPublishViewModel(application: Application) : AndroidViewModel(applica
private fun postVideo(jsonObject: JSONObject) {
processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true))
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
mApi.postBbsVideo(body)
.compose(observableToMain())
.subscribe(object : Response<JsonObject>() {

View File

@ -72,7 +72,7 @@ public class PackageChangeBroadcastReceiver extends BroadcastReceiver {
PackageHelper.refreshLocalPackageList();
String versionName = PackageUtils.getVersionNameByPackageName(packageName);
EBPackage installEb = new EBPackage(EBPackage.TYPE_INSTALLED, packageName, versionName);
EBPackage installEb = new EBPackage(EBPackage.TYPE_INSTALLED, packageName, versionName, false);
if (PackageUtils.isAppOnForeground(context)) {
PackageObserver.onPackageChanged(installEb, null);
EventBus.getDefault().post(installEb);
@ -102,7 +102,7 @@ public class PackageChangeBroadcastReceiver extends BroadcastReceiver {
InstallUtils.getInstance().removeUninstall(packageName);
PackageHelper.refreshLocalPackageList();
EBPackage uninstallEb = new EBPackage(EBPackage.TYPE_UNINSTALLED, packageName, "");
EBPackage uninstallEb = new EBPackage(EBPackage.TYPE_UNINSTALLED, packageName, "", false);
PackageObserver.onPackageChanged(uninstallEb, null);
EventBus.getDefault().post(uninstallEb);
if (webviewPackageName.equals(packageName)) {
@ -118,7 +118,7 @@ public class PackageChangeBroadcastReceiver extends BroadcastReceiver {
Utils.log(TAG, "替换了:" + packageName + "包名的程序");
String versionName = PackageUtils.getVersionNameByPackageName(packageName);
EBPackage updateEb = new EBPackage(EBPackage.TYPE_REPLACED, packageName, versionName);
EBPackage updateEb = new EBPackage(EBPackage.TYPE_REPLACED, packageName, versionName, false);
EventBus.getDefault().post(updateEb);
PackageObserver.onPackageChanged(updateEb, null);
if (webviewPackageName.equals(packageName)) {

View File

@ -1,6 +1,9 @@
package com.gh.gamecenter.search
import android.graphics.Color
import android.graphics.LinearGradient
import android.graphics.Shader
import android.graphics.Typeface
import android.graphics.drawable.GradientDrawable
import android.os.Bundle
import android.text.TextUtils
@ -15,6 +18,7 @@ import androidx.viewpager.widget.PagerAdapter
import com.gh.common.constant.Config
import com.gh.common.exposure.ExposureManager
import com.gh.common.filter.RegionSettingHelper
import com.gh.common.util.DirectUtils
import com.gh.common.util.NewFlatLogUtils
import com.gh.gamecenter.R
import com.gh.gamecenter.SearchActivity
@ -31,7 +35,7 @@ import com.gh.gamecenter.databinding.TabItemSearchDefaultRankBinding
import com.gh.gamecenter.db.ISearchHistoryDao
import com.gh.gamecenter.db.SearchHistoryDao
import com.gh.gamecenter.eventbus.EBSearch
import com.gh.gamecenter.feature.entity.DiscoveryTagEntity
import com.gh.gamecenter.feature.entity.HotTagEntity
import com.gh.gamecenter.feature.entity.SettingsEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.google.android.flexbox.FlexboxLayout
@ -43,7 +47,7 @@ import org.json.JSONObject
open class SearchDefaultFragment : BaseFragment<Any>() {
private var mSearchDiscoveryTagList: List<DiscoveryTagEntity>? = null
private var mHotTagList: List<HotTagEntity>? = null
protected var mRankList: List<SettingsEntity.Search.RankList>? = null
protected lateinit var mBinding: FragmentSearchDefaultBinding
@ -62,28 +66,28 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
private val mDao by lazy { provideDao() }
private val mSearchDiscoveryTagClickListener: (Int) -> Unit = {
val tag = mSearchDiscoveryTagList!![it]
val keyword = tag.keyword
if (keyword.isNotEmpty()) {
PageSwitchDataHelper.pushCurrentPageData(
hashMapOf(
Pair(PageSwitchDataHelper.PAGE_BUSINESS_TYPE, "游戏搜索-搜索发现"),
Pair(PageSwitchDataHelper.PAGE_BUSINESS_ID, tag.id ?: ""),
Pair(PageSwitchDataHelper.PAGE_BUSINESS_NAME, tag.text ?: " ")
)
private val mHotTagClickListener: (Int) -> Unit = {
val tag = mHotTagList!![it]
NewFlatLogUtils.logSearchHotTagClick(
tag.name ?: "",
tag.type ?: "",
tag.link ?: "",
tag.text ?: ""
)
DataLogUtils.uploadHotTagLog(context, tag.name)
PageSwitchDataHelper.pushCurrentPageData(
hashMapOf(
Pair(PageSwitchDataHelper.PAGE_BUSINESS_TYPE, "游戏搜索-热门标签"),
Pair(PageSwitchDataHelper.PAGE_BUSINESS_ID, tag.id ?: ""),
Pair(PageSwitchDataHelper.PAGE_BUSINESS_NAME, tag.name ?: " ")
)
SensorsBridge.trackEvent("SearchLabelClick", "label_name", tag.text ?: "", "label_id", tag.id ?: "")
SensorsBridge.trackSearchDiscoveryClick(
labelName = tag.text ?: "",
labelId = tag.id ?: "",
searchContent = keyword,
position = it
)
mViewModel?.add(keyword)
EventBus.getDefault().post(EBSearch("history", keyword))
Util_System_Keyboard.hideSoftKeyboardByIBinder(context, mBinding.historyFlex.windowToken)
}
)
SensorsBridge.trackEvent("SearchLabelClick", "label_name", tag.name ?: "", "label_id", tag.id ?: "")
val exposureEvent = ExposureEvent.createEvent(
null,
source = listOf(ExposureSource("首页搜索", ""), ExposureSource("热门标签", tag.name ?: ""))
)
DirectUtils.directToLinkPage(requireContext(), tag, "(搜索-${tag.name})", "", exposureEvent) // 不需要path
}
override fun getLayoutId(): Int {
@ -136,20 +140,16 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
}
mViewModel?.isExistRankList = mRankList?.isNotEmpty() == true
mSearchDiscoveryTagList = Config.getSettings()?.search?.discoveryTag
mViewModel?.isExistSearchDiscoveryTag = mSearchDiscoveryTagList?.isNotEmpty() == true
mHotTagList = Config.getSettings()?.search?.hotTag
mViewModel?.isExistHotTag = mHotTagList?.isNotEmpty() == true
updateHistorySearchView(null)
mViewModel?.historySearchLiveData?.observe(viewLifecycleOwner) {
updateHistorySearchView(it)
}
mBinding.searchDiscoveryTagFlexContainer.setLimitHeight(mFlexMaxHeight)
createFlexContent(
mBinding.searchDiscoveryTagFlex,
getTagListString(),
clickListener = mSearchDiscoveryTagClickListener
)
mBinding.hotTagFlexContainer.setLimitHeight(mFlexMaxHeight)
createFlexContent(mBinding.hotTagFlex, getTagListString(), true, clickListener = mHotTagClickListener)
initHeadView()
initRankViewPager()
}
@ -178,12 +178,12 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
})
}
}
mBinding.searchDiscoveryHeadContainer.headTitle.text = getString(R.string.search_hot)
mBinding.searchDiscoveryHeadContainer.headTitle.textSize = 16F
mBinding.searchDiscoveryHeadContainer.headActionTv.visibility = View.GONE
mBinding.searchDiscoveryTagHeadContainer.headTitle.text = getString(R.string.search_discovery_tag)
mBinding.searchDiscoveryTagHeadContainer.headTitle.textSize = 16F
mBinding.searchDiscoveryTagHeadContainer.headActionTv.visibility = View.GONE
mBinding.hotHeadContainer.headTitle.text = getString(R.string.search_hot)
mBinding.hotHeadContainer.headTitle.textSize = 16F
mBinding.hotHeadContainer.headActionTv.visibility = View.GONE
mBinding.hotTagHeadContainer.headTitle.text = getString(R.string.search_hot_tag)
mBinding.hotTagHeadContainer.headTitle.textSize = 16F
mBinding.hotTagHeadContainer.headActionTv.visibility = View.GONE
}
protected open fun initRankViewPager() {
@ -318,8 +318,8 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
mBinding.historyHeadContainer.root.visibility =
if (mViewModel?.isExistHistory == true) View.VISIBLE else View.GONE
mBinding.historyFlex.visibility = if (mViewModel?.isExistHistory == true) View.VISIBLE else View.GONE
mBinding.searchDiscoveryTagHeadContainer.root.layoutParams =
(mBinding.searchDiscoveryTagHeadContainer.root.layoutParams as ConstraintLayout.LayoutParams).apply {
mBinding.hotTagHeadContainer.root.layoutParams =
(mBinding.hotTagHeadContainer.root.layoutParams as ConstraintLayout.LayoutParams).apply {
setMargins(
0,
if (mViewModel?.isExistHistory == true) 16F.dip2px() else 0,
@ -327,22 +327,21 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
0
)
}
mBinding.searchDiscoveryHeadContainer.root.layoutParams =
(mBinding.searchDiscoveryHeadContainer.root.layoutParams as ConstraintLayout.LayoutParams).apply {
mBinding.hotHeadContainer.root.layoutParams =
(mBinding.hotHeadContainer.root.layoutParams as ConstraintLayout.LayoutParams).apply {
setMargins(
0,
if (mViewModel?.isExistHistory == false && mViewModel?.isExistSearchDiscoveryTag == false) 16F.dip2px() else 0,
if (mViewModel?.isExistHistory == false && mViewModel?.isExistHotTag == false) 16F.dip2px() else 0,
0,
0
)
}
mBinding.searchDiscoveryTagHeadContainer.root.visibility =
if (mViewModel?.isExistSearchDiscoveryTag == true) View.VISIBLE else View.GONE
mBinding.searchDiscoveryTagFlex.visibility =
if (mViewModel?.isExistSearchDiscoveryTag == true) View.VISIBLE else View.GONE
mBinding.searchDiscoveryHeadContainer.root.visibility =
mBinding.hotTagHeadContainer.root.visibility =
if (mViewModel?.isExistHotTag == true) View.VISIBLE else View.GONE
mBinding.hotTagFlex.visibility = if (mViewModel?.isExistHotTag == true) View.VISIBLE else View.GONE
mBinding.hotHeadContainer.root.visibility =
if (mViewModel?.isExistHotSearch == true) View.VISIBLE else View.GONE
mBinding.searchDiscoveryList.visibility = if (mViewModel?.isExistHotSearch == true) View.VISIBLE else View.GONE
mBinding.hotList.visibility = if (mViewModel?.isExistHotSearch == true) View.VISIBLE else View.GONE
mBinding.rankTabLayout.visibility = if (mViewModel?.isExistRankList == true) View.VISIBLE else View.GONE
mBinding.rankTabIndicator.visibility = if (mViewModel?.isExistRankList == true) View.VISIBLE else View.GONE
mBinding.rankViewPager.visibility = if (mViewModel?.isExistRankList == true) View.VISIBLE else View.GONE
@ -364,9 +363,9 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
private fun getTagListString(): List<String> {
val list = ArrayList<String>()
if (mSearchDiscoveryTagList != null) {
for (entity in mSearchDiscoveryTagList!!) {
entity.text?.let { list.add(it) }
if (mHotTagList != null) {
for (entity in mHotTagList!!) {
entity.name?.let { list.add(it) }
}
}
return list
@ -375,6 +374,7 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
fun createFlexContent(
flexView: FlexboxLayout,
contentList: List<String>?,
isHotTag: Boolean = false,
clickListener: (Int) -> Unit
) {
@ -388,12 +388,16 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
val params = FlexboxLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 24F.dip2px())
flexCell.layoutParams = params
flexCell.setSingleLine()
flexCell.ellipsize = TextUtils.TruncateAt.END
flexCell.gravity = Gravity.CENTER
flexCell.textSize = 12F
flexCell.text = StringUtils.shrinkStringWithDot(contentList[index], 6)
flexCell.setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(requireContext()))
if (isHotTag && !mHotTagList.isNullOrEmpty() && mHotTagList!![index].isGuessSearch) {
createSmartHotTagStyle(flexCell, contentList[index])
} else {
flexCell.setSingleLine()
flexCell.ellipsize = TextUtils.TruncateAt.END
flexCell.gravity = Gravity.CENTER
flexCell.textSize = 12F
flexCell.text = StringUtils.shrinkStringWithDot(contentList[index], 6)
flexCell.setTextColor(com.gh.gamecenter.common.R.color.text_secondary.toColor(requireContext()))
}
flexCell.setPadding(8F.dip2px(), 0, 8F.dip2px(), 0)
flexCell.background = if (mIsDarkModeOn) GradientDrawable().apply {
setStroke(0.5F.dip2px(), Color.parseColor("#21FFFFFF"))
@ -405,6 +409,30 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
}
}
private fun createSmartHotTagStyle(flexCell: TextView, name: String) {
flexCell.setDrawableStart(R.drawable.ic_smart_search)
flexCell.compoundDrawablePadding = 4F.dip2px()
flexCell.gravity = Gravity.CENTER_VERTICAL
flexCell.typeface = Typeface.DEFAULT_BOLD
flexCell.textSize = 12F
flexCell.text = StringUtils.shrinkStringWithDot(name, 6)
flexCell.setTextColor(Color.WHITE)
val colors =
intArrayOf(com.gh.gamecenter.common.R.color.text_FFB749.toColor(requireContext()), com.gh.gamecenter.common.R.color.text_FF6D3C.toColor(requireContext()))
val position = floatArrayOf(0F, 1F)
val linearGradient = LinearGradient(
0F,
0F,
flexCell.paint.textSize * flexCell.text.length,
0F,
colors,
position,
Shader.TileMode.CLAMP
)
flexCell.paint.shader = linearGradient
flexCell.invalidate()
}
private fun postExposureEvent(index: Int) {
mRankList?.safelyGetInRelease(index)?.content?.forEach {
if (it.link.type == "game") {
@ -419,15 +447,11 @@ open class SearchDefaultFragment : BaseFragment<Any>() {
super.onDarkModeChanged()
initHeadView()
mBinding.rootContainer.setBackgroundColor(com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext()))
mBinding.searchDiscoveryList.adapter?.run {
mBinding.hotList.adapter?.run {
notifyItemRangeChanged(0, itemCount)
}
mViewModel?.historySearchLiveData?.value?.let { updateHistorySearchView(it) }
createFlexContent(
mBinding.searchDiscoveryTagFlex,
getTagListString(),
clickListener = mSearchDiscoveryTagClickListener
)
createFlexContent(mBinding.hotTagFlex, getTagListString(), true, clickListener = mHotTagClickListener)
}
protected open fun provideDao(): ISearchHistoryDao =

View File

@ -11,7 +11,7 @@ class SearchDefaultViewModel(private val dao: ISearchHistoryDao) : ViewModel() {
it
}
var isExistHotSearch: Boolean = false
var isExistSearchDiscoveryTag: Boolean = false
var isExistHotTag: Boolean = false
var isExistHistory: Boolean = false
var isExistRankList: Boolean = false

View File

@ -214,7 +214,7 @@ class SearchGameIndexFragment : ListFragment<GameEntity, SearchGameResultViewMod
// 安装/卸载 事件
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(busFour: EBPackage) {
if (busFour.isInstalledOrUninstalled()) {
if (!busFour.fromInit && busFour.isInstalledOrUninstalled()) {
mAdapter?.notifyDataSetChanged()
}
}

View File

@ -58,7 +58,7 @@ class SearchGameResultAdapter(
private val dao: ISearchHistoryDao,
val listViewModel: SearchGameResultViewModel,
val entrance: String,
val type: String,
var type: String,
val sourceEntrance: String
) : ListAdapter<SearchItemData>(context), IExposable {

View File

@ -376,6 +376,7 @@ open class SearchGameResultFragment : ListFragment<GameEntity, SearchGameResultV
this.mKey = key
this.mType = type
mAdapter?.key = key
mAdapter?.type = type
mAdapter?.clearAdIdSet()
mListViewModel?.updateSearchKeyWithType(key, type)
mListViewModel?.clearSearchSubjects()
@ -423,7 +424,7 @@ open class SearchGameResultFragment : ListFragment<GameEntity, SearchGameResultV
// 安装/卸载 事件
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(busFour: EBPackage) {
if (busFour.isInstalledOrUninstalled()) {
if (!busFour.fromInit && busFour.isInstalledOrUninstalled()) {
mAdapter?.notifyDataSetChanged()
}
}

View File

@ -3,9 +3,9 @@ package com.gh.gamecenter.search.viewmodel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.gh.gamecenter.SearchActivity
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.utils.SensorsBridge
import io.reactivex.disposables.CompositeDisposable
class SearchTabViewModel : ViewModel() {
@ -21,7 +21,8 @@ class SearchTabViewModel : ViewModel() {
GlobalActivityManager.getCurrentPageEntity().pageName,
location,
searchKeyAndType.value?.first ?: "",
searchKeyAndType.value?.second ?: "",
searchKeyAndType.value?.let {
SearchActivity.toTrackSearchType(it.second) } ?: "",
text ?: "",
position
)

View File

@ -16,7 +16,9 @@ import com.lightgame.utils.Utils.toast
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import retrofit2.HttpException
class AddKaiFuViewModel(application: Application) : AndroidViewModel(application) {
@ -266,7 +268,7 @@ class AddKaiFuViewModel(application: Application) : AndroidViewModel(application
private fun postData(postList: ArrayList<ServerCalendarEntity>) {
val body = RequestBody.create(MediaType.parse("application/json"), GsonUtils.toJson(postList))
val body = GsonUtils.toJson(postList).toRequestBody("application/json".toMediaTypeOrNull())
RetrofitManager.getInstance().api.addKaifu(body, mGameId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())

View File

@ -11,7 +11,9 @@ import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody
import org.json.JSONObject
import retrofit2.HttpException
@ -35,7 +37,7 @@ class PatchKaifuViewModel(application: Application) : AndroidViewModel(applicati
val jsonObject = JSONObject()
jsonObject.put("note", patchName)
jsonObject.put("remark", patchRemark)
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
apiService.patchKaifu(body, gameId, serverEntity!!.id)
} else {
apiService.deleteKaifu(gameId, serverEntity!!.id)

View File

@ -207,7 +207,7 @@ open class SubjectListFragment : LazyListFragment<GameEntity, SubjectListViewMod
// 安装/卸载 事件
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(busFour: EBPackage) {
if (busFour.isInstalledOrUninstalled()) {
if (!busFour.fromInit && busFour.isInstalledOrUninstalled()) {
mAdapter?.notifyDataSetChanged()
}
}

View File

@ -197,7 +197,7 @@ class TagsListFragment : ListFragment<GameEntity, TagsListViewModel>() {
// 安装/卸载 事件
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(busFour: EBPackage) {
if (busFour.isInstalledOrUninstalled()) {
if (!busFour.fromInit && busFour.isInstalledOrUninstalled()) {
mAdapter?.notifyDataSetChanged()
}
}

View File

@ -26,7 +26,9 @@ import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody
import org.json.JSONObject
import retrofit2.HttpException
@ -57,7 +59,7 @@ class UploadVideoViewModel(application: Application) : AndroidViewModel(applicat
private fun postVideo(jsonObject: JSONObject) {
processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true))
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
mApi.postVideo(body)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
@ -121,7 +123,7 @@ class UploadVideoViewModel(application: Application) : AndroidViewModel(applicat
private fun patchVideo(jsonObject: JSONObject, videoId: String) {
processDialog.postValue(WaitingDialogFragment.WaitingDialogData("提交中...", true))
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
mApi.patchVideo(body, videoId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
@ -188,7 +190,7 @@ class UploadVideoViewModel(application: Application) : AndroidViewModel(applicat
patchVideo(JSONObject(GsonUtils.toJson(videoEntity)), videoEntity.id)
} else if (isDraft) {
val draftData = JSONObject(videoEntity.toJson()).put("local_path", videoPath).toString()
val body = RequestBody.create(MediaType.parse("application/json"), draftData)
val body = draftData.toRequestBody("application/json".toMediaTypeOrNull())
postDraft(body)
} else {
var videoHeight = 0

View File

@ -19,7 +19,9 @@ import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import io.reactivex.subjects.PublishSubject
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody
import org.json.JSONException
import org.json.JSONObject
@ -66,7 +68,7 @@ class VoteViewModel(application: Application, private val mGameId: String = "")
requestMap["version_code"] = installGameEntity.versionCode
val body = RequestBody.create(
MediaType.parse("application/json"),
"application/json".toMediaTypeOrNull(),
GsonUtils.toJson(requestMap)
)
RetrofitManager.getInstance().api.postPlatformRequestApk(installGameEntity.platformRequestsId, body)
@ -99,7 +101,7 @@ class VoteViewModel(application: Application, private val mGameId: String = "")
} catch (e: JSONException) {
e.printStackTrace()
}
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
val responseBodyObservable = if (isNewVote) {
RetrofitManager.getInstance().api.addVersionVote(body, mGameId)
} else if (isVoted) {

View File

@ -20,6 +20,9 @@ import com.gh.gamecenter.entity.DiverterEntity
import com.gh.gamecenter.entity.MultiTabNav
import com.gh.gamecenter.home.custom.model.CustomPageData
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.Observable
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
@ -59,10 +62,13 @@ class MainWrapperRepository {
private val mTabSelectEventFlow = MutableSharedFlow<MainSelectedEvent>()
val tabSelectEventFlow = mTabSelectEventFlow as SharedFlow<MainSelectedEvent>
private var mDisposable: Disposable? = null
private var mCheckGidCount = 0
fun init() {
// 若 timeout 后数据未加载完成,则即便还没有回调也使用默认数据生成底部 tab
emitDefaultTabDataAfterTimeout()
getBypassList()
checkGidAndGetBypassList()
}
/**
@ -149,8 +155,33 @@ class MainWrapperRepository {
}
}
private fun checkGidAndGetBypassList() {
if (HaloApp.getInstance().gid.isNullOrEmpty()) {
stopCheckGid()
mDisposable = Observable.interval(100, TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.computation())
.subscribe({
mCheckGidCount++
if (!HaloApp.getInstance().gid.isNullOrEmpty() || mCheckGidCount >= CHECK_GID_MAX_COUNT) {
stopCheckGid()
getBypassList()
}
}, {
stopCheckGid()
})
} else {
getBypassList()
}
}
private fun stopCheckGid() {
mDisposable?.dispose()
mDisposable = null
mCheckGidCount = 0
}
@SuppressLint("CheckResult")
fun getBypassList() {
private fun getBypassList() {
val isInstallFirstAccess = TimeUtils.isToday(SPUtils.getLong(Constants.SP_BRAND_NEW_FIRST_LAUNCH_TIME) / 1000).toString()
mNewApi.getDiverterList(isInstallFirstAccess, BYPASS_TYPE_BOTTOM_TAB)
.subscribeOn(Schedulers.computation())
@ -294,6 +325,7 @@ class MainWrapperRepository {
companion object : SingletonHolder<MainWrapperRepository>({ MainWrapperRepository() }) {
private const val BYPASS_TIME_OUT = 1000L
private const val CHECK_GID_MAX_COUNT = 5
const val BYPASS_TYPE_BOTTOM_TAB = "bottom_tab"
}
}

View File

@ -22,7 +22,9 @@ import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.transformWhile
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody
import org.json.JSONObject
import retrofit2.HttpException
@ -93,7 +95,7 @@ class MainWrapperViewModel(application: Application, private val mRepository: Ma
fun postMessageRead(messageId: String) {
val jsonObject = JSONObject()
jsonObject.put("type", "system_message")
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
RetrofitManager.getInstance().api.postMessageRead(UserManager.getInstance().userId, messageId, body)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())

View File

@ -99,7 +99,7 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar
private val viewModel: SearchToolbarTabWrapperViewModel by lazy {
viewModelProviderFromParent(
SearchToolbarTabWrapperViewModel.Factory(multiTabNavId, noTabLinkEntity?.link ?: ""),
multiTabNavId
multiTabNavId + (noTabLinkEntity?.link ?: "")
)
}

View File

@ -3,7 +3,6 @@ package com.gh.ndownload.suspendwindow
import android.app.Activity
import android.app.Application
import android.app.Application.ActivityLifecycleCallbacks
import android.os.Build
import android.os.Bundle
import androidx.core.view.ViewCompat
import com.gh.gamecenter.common.constant.Constants
@ -128,7 +127,7 @@ class NDownloadDrawOverlayPermissionWindowController(val application: Applicatio
SensorsBridge.trackDownloadSuspendedWindowGuideShow(
gameId = downloadEntity.gameId,
gameName = downloadEntity.name,
gameSchemeType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位",
gameSchemaType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位",
gameType = downloadEntity.categoryChinese,
downloadStatus = downloadEntity.getMetaExtra(Constants.DOWNLOAD_STATUS_IN_CHINESE),
downloadType = if (downloadEntity.asVGame()) "畅玩下载" else "本地下载"

View File

@ -48,10 +48,17 @@ abstract class NDownloadSuspendWindow<T : View>(
fun attach() {
if (!isAttached) {
_isAttached = true
windowManager.addView(root, layoutParams)
context.registerComponentCallbacks(this)
onAttach()
try {
_isAttached = true
windowManager.addView(root, layoutParams)
context.registerComponentCallbacks(this)
onAttach()
} catch (e: Throwable) {
// 处理“Unable to add window android.view.ViewRootImpl$W@7bc9502 -- permission denied for window type 2038”的异常
// 目前Sentry上仅Z10型号的手机报这个错误Android 8.1.0这里明明已经授予了SYSTEM_ALERT_WINDOW权限但是就是会抛异常= =,只能暴力捕获处理了。。。
// 相关异常的链接https://sentry.shanqu.cc/organizations/lightgame/issues/407275/?project=22
_isAttached = false
}
}
}

View File

@ -15,7 +15,9 @@ import com.halo.assistant.HaloApp
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody
import org.json.JSONObject
import retrofit2.HttpException
@ -52,9 +54,8 @@ class ManuallyRealNameViewModel(application: Application) : AndroidViewModel(app
fun postCertificationReview(idCardEntity: IdCardEntity) {
val userInfoEntity = UserInfoEntity()
userInfoEntity.idCard = idCardEntity
val body = RequestBody.create(
MediaType.parse("application/json"), GsonUtils.toJson(userInfoEntity)
)
val body = GsonUtils.toJson(userInfoEntity)
.toRequestBody("application/json".toMediaTypeOrNull())
RetrofitManager.getInstance().api.postCertificationReview(body)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())

View File

@ -19,7 +19,9 @@ import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody
import org.json.JSONObject
import retrofit2.HttpException
@ -39,7 +41,7 @@ class VerifyPhoneViewModel(application: Application) : AndroidViewModel(applicat
params["mobile"] = phoneNum
val jsonObject = JSONObject(params as Map<*, *>)
jsonObject.put("device", device)
val body: RequestBody = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
val body: RequestBody = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
api.verifyPhone(1, body)
.subscribeOn(Schedulers.io())
@ -80,7 +82,7 @@ class VerifyPhoneViewModel(application: Application) : AndroidViewModel(applicat
params["code"] = code
val jsonObject = JSONObject(params as Map<*, *>)
jsonObject.put("device", device)
val body: RequestBody = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
val body: RequestBody = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
api.verifyPhone(2, body)
.subscribeOn(Schedulers.io())

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -36,7 +36,7 @@
</com.gh.gamecenter.common.view.LimitHeightLinearLayout>
<include
android:id="@+id/searchDiscoveryTagHeadContainer"
android:id="@+id/hotTagHeadContainer"
layout="@layout/layout_subject_head"
android:layout_width="match_parent"
android:layout_height="48dp"
@ -45,14 +45,14 @@
app:layout_constraintTop_toBottomOf="@id/history_flex_container" />
<com.gh.gamecenter.common.view.LimitHeightLinearLayout
android:id="@+id/search_discovery_tag_flex_container"
android:id="@+id/hot_tag_flex_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/ui_surface"
app:layout_constraintTop_toBottomOf="@id/searchDiscoveryTagHeadContainer">
app:layout_constraintTop_toBottomOf="@id/hotTagHeadContainer">
<com.google.android.flexbox.FlexboxLayout
android:id="@+id/search_discovery_tag_flex"
android:id="@+id/hot_tag_flex"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="16dp"
@ -62,21 +62,21 @@
</com.gh.gamecenter.common.view.LimitHeightLinearLayout>
<include
android:id="@+id/searchDiscoveryHeadContainer"
android:id="@+id/hotHeadContainer"
layout="@layout/layout_subject_head"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginTop="16dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/search_discovery_tag_flex_container" />
app:layout_constraintTop_toBottomOf="@id/hot_tag_flex_container" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/search_discovery_list"
android:id="@+id/hot_list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:overScrollMode="never"
app:layout_constrainedHeight="true"
app:layout_constraintTop_toBottomOf="@+id/searchDiscoveryHeadContainer" />
app:layout_constraintTop_toBottomOf="@+id/hotHeadContainer" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/rankTabLayout"
@ -91,7 +91,7 @@
app:tabMode="scrollable"
app:tabIndicator="@null"
app:tabRippleColor="@color/transparent"
app:layout_constraintTop_toBottomOf="@+id/search_discovery_list"
app:layout_constraintTop_toBottomOf="@+id/hot_list"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />

View File

@ -18,7 +18,7 @@
<string name="download_startall">全部開始</string>
<string name="search_searching">搜索中...</string>
<string name="search_hot">熱門搜索</string>
<string name="search_discovery_tag">搜索發現</string>
<string name="search_hot_tag">熱門標簽</string>
<string name="search_history">歷史搜索</string>
<string name="news_concenrn_game_mine">我關註的遊戲</string>
<string name="news_search_input">請輸入搜索關鍵字</string>

View File

@ -18,7 +18,7 @@
<string name="download_startall">全部开始</string>
<string name="search_searching">搜索中...</string>
<string name="search_hot">热门搜索</string>
<string name="search_discovery_tag">搜索发现</string>
<string name="search_hot_tag">热门标签</string>
<string name="search_history">历史搜索</string>
<string name="news_concenrn_game_mine">我关注的游戏</string>
<string name="news_search_input">请输入搜索关键字</string>

View File

@ -17,8 +17,8 @@ buildscript {
password("u9gZYH4MQEwLLQZK")
}
}
maven { url 'https://jitpack.io' }
maven { url "https://maven.google.com" }
maven { url 'https://jitpack.io' }
}
dependencies {
@ -41,7 +41,6 @@ allprojects {
google()
jcenter()
mavenCentral()
maven { url 'https://jitpack.io' }
maven { url 'https://maven.aliyun.com/repository/public' }
maven { url 'https://maven.aliyun.com/repository/central'}
maven { url 'https://maven.aliyun.com/nexus/content/repositories/releases/' }
@ -55,6 +54,7 @@ allprojects {
// 配置HMS Core SDK的Maven仓地址。
maven { url 'https://developer.huawei.com/repo/' }
maven { url 'https://developer.hihonor.com/repo' }
maven { url 'https://jitpack.io' }
}
}
task clean(type: Delete) {

View File

@ -49,6 +49,7 @@ class GhTransform(var project: Project) : Transform() {
mTransformHelper.addTransformer(RoomTransformer())
mTransformHelper.addTransformer(ActivityTransformer())
mTransformHelper.addTransformer(AppCompatEditTextTransformer())
mTransformHelper.addTransformer(MiniGameWebViewTransformer())
}
/**

View File

@ -0,0 +1,47 @@
package com.gh.gamecenter.plugin.transform
import javassist.ClassPool
import javassist.CtClass
import javassist.NotFoundException
import javassist.bytecode.ClassFile
import java.io.BufferedInputStream
import java.io.DataInputStream
import java.io.InputStream
class MiniGameWebViewTransformer : Transformer {
private val classPool = ClassPool.getDefault()
override fun getModifyClassName(): String {
return "QUAUtil"
}
override fun modifyClass(filePath: String, inputStream: InputStream): CtClass? {
if (filePath.contains(getModifyClassName())) {
println("发现 QUAUtil")
val classFile = ClassFile(DataInputStream(BufferedInputStream(inputStream)))
val ctClass = classPool.get(classFile.name)
if (ctClass.isFrozen) {
ctClass.defrost()
}
// 使用 try catch 包裹找到的第一个 getSystemUA 方法 (若能找到的话)
try {
val ctMethod = ctClass.getDeclaredMethod("getSystemUA")
val body = "{ if (systemUA != null) { return systemUA; } systemUA = java.net.URLEncoder.encode(System.getProperty(\"http.agent\"), \"UTF-8\"); return systemUA; }"
ctMethod.setBody(body)
println("修改 getSystemUA 方法")
} catch (e: NotFoundException) {
e.printStackTrace()
}
return ctClass
}
return null
}
}

View File

@ -49,7 +49,7 @@ ext {
rxAndroid2 = "2.1.1"
rxBinding2 = "2.1.1"
retrofit = "2.3.0"
okHttp = "3.12.13"
okHttp = "4.11.0"
gson = "2.8.2"
zxing = "3.2.1"
fresco = "2.6.0"

View File

@ -18,6 +18,7 @@ object NewLogUtils {
private const val KEY_CONTENT_ID = "content_id"
private const val KEY_CONTENT_TITLE = "content_title"
private const val KEY_HELP_ID = "help_id"
private const val KEY_QA_COLLECTION = "qa_collection"
private const val KEY_SEARCH_KEY = "search_key"
private fun log(jsonObject: JSONObject, logStore: String = "event", uploadImmediately: Boolean = false) {
@ -53,10 +54,11 @@ object NewLogUtils {
}
//点击QA更多
fun logClickQaMoreBtn(helpId: String) {
fun logClickQaMoreBtn(helpId: String, qaCollection: String) {
val json = json {
KEY_EVENT to "qa_click_title_more"
KEY_HELP_ID to helpId
KEY_QA_COLLECTION to qaCollection
KEY_META to LogUtils.getMetaObject()
KEY_LAUNCH_ID to Tracker.launchId
KEY_SESSION_ID to Tracker.sessionId

View File

@ -150,7 +150,7 @@ class HelpAndFeedbackFragment : BaseLazyFragment() {
val layoutManager = FixLinearLayoutManager(requireContext(), RecyclerView.HORIZONTAL, false)
mSnapHelper = LeftPagerSnapHelper()
mHelpVideoAdapter = HelpVideoAdapter(requireContext(), mSnapHelper!!, layoutManager, helpVideoRv)
mHelpVideoAdapter = HelpVideoAdapter(requireContext(), viewLifecycleOwner, mSnapHelper!!, layoutManager, helpVideoRv)
(helpVideoRv.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false
helpVideoRv.layoutManager = layoutManager
helpVideoRv.adapter = mHelpVideoAdapter
@ -209,9 +209,7 @@ class HelpAndFeedbackFragment : BaseLazyFragment() {
mViewModel.selectedCategory.name == HelpAndFeedbackViewModel.MY_RELATED_QA_NAME
)
)
if (mViewModel.selectedCategory.id.isNotEmpty()) {
NewLogUtils.logClickQaMoreBtn(mViewModel.selectedCategory.id)
}
NewLogUtils.logClickQaMoreBtn(mViewModel.selectedCategory.id, mViewModel.selectedCategory.name)
}
}

View File

@ -5,6 +5,8 @@ import android.os.Handler
import android.os.Message
import android.view.ViewGroup
import android.view.ViewGroup.MarginLayoutParams
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.alibaba.android.arouter.launcher.ARouter
@ -20,6 +22,7 @@ import java.lang.ref.WeakReference
class HelpVideoAdapter(
context: Context,
private val mLifecycleOwner: LifecycleOwner,
private val mSnapHelper: LeftPagerSnapHelper,
private val mLayoutManager: LinearLayoutManager,
private val mRecyclerView: RecyclerView
@ -27,6 +30,17 @@ class HelpVideoAdapter(
private var mHelpVideoList = arrayListOf<HelpVideo>()
private val mLooperHandle = LooperHandle(this)
private val mSlideLooperKey = 102
private val mLifecycleObserver = object : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) {
super.onResume(owner)
startScroll()
}
override fun onPause(owner: LifecycleOwner) {
super.onPause(owner)
stopScroll()
}
}
fun submitList(helpVideoList: List<HelpVideo>) {
mHelpVideoList = ArrayList(helpVideoList)
@ -122,6 +136,16 @@ class HelpVideoAdapter(
mLooperHandle.removeMessages(mSlideLooperKey)
}
override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
super.onViewAttachedToWindow(holder)
mLifecycleOwner.lifecycle.addObserver(mLifecycleObserver)
}
override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
super.onViewDetachedFromWindow(holder)
mLifecycleOwner.lifecycle.removeObserver(mLifecycleObserver)
}
class LooperHandle(adapter: HelpVideoAdapter) : Handler() {
private val mWeakReference: WeakReference<HelpVideoAdapter> = WeakReference(adapter)

View File

@ -22,7 +22,7 @@ class HelpContentAdapter(
context: Context,
private val mFragment: HelpContentFragment,
private val mViewModel: NormalListViewModel<HelpEntity>,
private val mQaId: String?,
private val mIsFromHelpAndFeedback: Boolean,
private val mQaCollectionId: String?,
private val mNavigationTitle: String,
private val searchType: String,
@ -103,7 +103,7 @@ class HelpContentAdapter(
)
} else {
NewLogUtils.logEnterQaContent(
"其他位置",
if (mIsFromHelpAndFeedback) "帮助与反馈" else "其他位置",
entity.id,
HtmlUtils.filterHtmlLabel(entity.title),
entity.helpId,

View File

@ -60,7 +60,7 @@ class HelpContentFragment : ListFragment<HelpEntity, NormalListViewModel<HelpEnt
requireContext(),
this,
mListViewModel,
mQaId,
!mCategoryId.isNullOrEmpty() || mIsMyRelatedQA,
mQaCollectionId,
mNavigationTitle,
mSearchType,

View File

@ -61,7 +61,7 @@ class HelpQaCategoryAdapter(val context: Context, private val mQaCollectionId: S
} else {
MtaHelper.onEvent("意见反馈", "使用帮助点击", "点击更多+${helpCategoryEntity.name}")
}
NewLogUtils.logClickQaMoreBtn(helpCategoryEntity.id)
NewLogUtils.logClickQaMoreBtn(helpCategoryEntity.id, helpCategoryEntity.name)
}
}
}

View File

@ -18,7 +18,6 @@ import cn.com.chinatelecom.account.api.CtAuth
import cn.jiguang.verifysdk.api.*
import com.alibaba.android.arouter.launcher.ARouter
import com.gh.gamecenter.common.base.GlobalActivityManager.getCurrentPageEntity
import com.gh.gamecenter.common.base.GlobalActivityManager.getLastPageEntity
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.databinding.SetWaitDialogBinding
import com.gh.gamecenter.common.utils.*
@ -50,7 +49,6 @@ object LoginHelper {
//请注意,这里有可能会出现内存泄漏,需要及时清理
@SuppressLint("StaticFieldLeak")
private var backgroundView: View? = null
private var loggingDialog: Dialog? = null
private var cbPrivacy: CheckBox? = null
private var loginProvider: ILoginProvider? = null
@ -85,20 +83,26 @@ object LoginHelper {
fun loginAuth(context: Context, entrance: String, callback: (() -> Unit)?) {
runOnUiThread {
val dialogContext = DialogHelper.checkDialogContext(context)
if (dialogContext is Activity && dialogContext.isFinishing) return@runOnUiThread
preDialog = dialogContext?.let {
Dialog(it, com.gh.gamecenter.common.R.style.DialogWindowTransparent).apply {
val binding = SetWaitDialogBinding.inflate(LayoutInflater.from(dialogContext)).apply {
setWaitMessage.text = "请求登录中"
if (dialogContext is Activity && (dialogContext.isFinishing || dialogContext.isDestroyed)) return@runOnUiThread
preDialog = try {
dialogContext?.let {
Dialog(it, com.gh.gamecenter.common.R.style.DialogWindowTransparent).apply {
val binding = SetWaitDialogBinding.inflate(LayoutInflater.from(dialogContext)).apply {
setWaitMessage.text = "请求登录中"
}
requestWindowFeature(Window.FEATURE_NO_TITLE)
setContentView(binding.root)
setCanceledOnTouchOutside(false)
show()
}
requestWindowFeature(Window.FEATURE_NO_TITLE)
setContentView(binding.root)
setCanceledOnTouchOutside(false)
show()
}
} catch (e: Exception) {
// no implement
null
}
}
}
isDarkMode = DarkModeUtils.isDarkModeOn(context)
setUiConfig(context, callback)
val settings = LoginSettings()
@ -136,7 +140,6 @@ object LoginHelper {
}
8 -> { // 点击了一键登录按钮
showLoggingDialog()
SensorsBridge.trackEvent("Login", "login_type", "一键登录")
}
}
@ -156,7 +159,6 @@ object LoginHelper {
}
LOGIN_AUTH_CODE_FAILURE -> {
dismissDialog()
getLoginProvider()?.startCodeLoginPageFromQuickLogin(openAuthPageSuccess, context, callback)
}
}
@ -167,9 +169,6 @@ object LoginHelper {
if (preDialog?.isShowing == true) {
preDialog?.dismiss()
}
if (loggingDialog?.isShowing == true) {
loggingDialog?.dismiss()
}
}
private fun setUiConfig(context: Context, callback: (() -> Unit)?) {
@ -259,15 +258,6 @@ object LoginHelper {
}
}
private fun showLoggingDialog() {
AppManager.getInstance().recentActiveActivity?.run {
val dialogContext = com.gh.gamecenter.common.utils.DialogHelper.checkDialogContext(this)
if (dialogContext == null || (dialogContext is Activity && dialogContext.isFinishing)) return
loggingDialog = getLoginProvider()?.createLoggingDialog(dialogContext)
loggingDialog?.show()
}
}
private fun showPrivacyCheckDialog(
authContext: Context,
context: Context,
@ -332,7 +322,6 @@ object LoginHelper {
fun release() {
backgroundView = null
loggingDialog = null
preDialog = null
isPolicyCheck = false
loginToken = ""

View File

@ -63,6 +63,11 @@ class CustomLayoutInflaterFactory(
view.dimOnDarkMode()
}
// 为每个Fragment的子view添加对应Fragment的Tag
parent?.getTag(androidx.fragment.R.id.fragment_container_view_tag)?.let {
view?.setTag(androidx.fragment.R.id.fragment_container_view_tag, it)
}
return view
}

View File

@ -12,6 +12,7 @@ import java.util.concurrent.TimeUnit;
import okhttp3.Cache;
import okhttp3.OkHttpClient;
import okhttp3.brotli.BrotliInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
@ -38,6 +39,7 @@ public abstract class BaseRetrofitManager {
final Cache cache = new Cache(new File(OkHttpCache.getCachePath(context)), 10 * 1024 * 1024); // 10Mb
return Injection.provideRetrofitBuilder()
.addInterceptor(BrotliInterceptor.INSTANCE)
.addInterceptor(new OkHttpCacheInterceptor(context))
.addInterceptor(new OkHttpRetryInterceptor(context, maxRetryCount))
.addInterceptor(new ChuckerInterceptor(context, new ChuckerCollector(context, true, RetentionManager.Period.ONE_DAY)))

View File

@ -13,7 +13,9 @@ import com.gh.gamecenter.core.provider.IUserManagerProvider
import com.gh.gamecenter.core.utils.MtaHelper
import com.lightgame.config.CommonDebug
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
import java.io.IOException
/**
@ -43,12 +45,12 @@ class OkHttpRetryInterceptor constructor(context: Context, val maxRetryCount: In
var tryCount = 0
val token = chain.request().header("token")
val url = request.url().toString()
while ((response == null || (token != null && response.code() == 401 && (!url.contains("refresh")))) // 排除刷新token接口避免进入死循环
val url = request.url.toString()
while ((response == null || (token != null && response.code == 401 && (!url.contains("refresh")))) // 排除刷新token接口避免进入死循环
&& ++tryCount <= maxRetryCount
) {
if (CommonDebug.IS_DEBUG) {
CommonDebug.logMethodWithParams(this, "Retrying ${request.url()} for $tryCount")
CommonDebug.logMethodWithParams(this, "Retrying ${request.url} for $tryCount")
}
if (url.contains("users:validate") && !TextUtils.isEmpty(request.header("retry"))
@ -70,7 +72,7 @@ class OkHttpRetryInterceptor constructor(context: Context, val maxRetryCount: In
tryCount = maxRetryCount + 1 // 只要token刷新异常直接主动退出登录
if (e != null && e.isNotEmpty()) {
response =
response?.newBuilder()?.body(ResponseBody.create(MediaType.parse("application/json"), e))
response?.newBuilder()?.body(e.toResponseBody("application/json".toMediaTypeOrNull()))
?.build()
}
})
@ -81,9 +83,9 @@ class OkHttpRetryInterceptor constructor(context: Context, val maxRetryCount: In
val buildConfig =
ARouter.getInstance().build(RouteConsts.provider.buildConfig).navigation() as IBuildConfigProvider
// 上报网络错误,过滤 404 以及非用户可感知的请求
val api = pathSegmentsToString(request.url().pathSegments())
val api = pathSegmentsToString(request.url.pathSegments)
if (tryCount == maxRetryCount + 1
&& (response == null || response?.code() != 404)
&& (response == null || response?.code != 404)
&& isUserAwareApi(api)
) {
MtaHelper.onEvent(

View File

@ -68,7 +68,9 @@ 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
import org.json.JSONArray
import org.json.JSONObject
import java.io.*
@ -652,25 +654,25 @@ fun String.copyTextAndToast(toastText: String = "复制成功") {
fun Map<String, String>.createRequestBody(): RequestBody {
val json = GsonUtils.toJson(this)
return RequestBody.create(MediaType.parse("application/json"), json)
return json.toRequestBody("application/json".toMediaTypeOrNull())
}
fun Map<String, Any>.createRequestBodyAny(): RequestBody {
val json = GsonUtils.toJson(this)
return RequestBody.create(MediaType.parse("application/json"), json)
return json.toRequestBody("application/json".toMediaTypeOrNull())
}
fun Any.toRequestBody(): RequestBody {
val json = GsonUtils.toJson(this)
return RequestBody.create(MediaType.parse("application/json"), json)
return json.toRequestBody("application/json".toMediaTypeOrNull())
}
fun JSONObject.toRequestBody(): RequestBody {
return RequestBody.create(MediaType.parse("application/json"), this.toString())
return this.toString().toRequestBody("application/json".toMediaTypeOrNull())
}
fun JSONArray.toRequestBody(): RequestBody {
return RequestBody.create(MediaType.parse("application/json"), this.toString())
return this.toString().toRequestBody("application/json".toMediaTypeOrNull())
}
// 对在浏览器(WebView)显示的路径进行转码

View File

@ -8,8 +8,14 @@ import android.graphics.drawable.ColorDrawable
import android.net.Uri
import android.os.Environment
import android.text.TextUtils
import android.view.View
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.alibaba.android.arouter.launcher.ARouter
import com.facebook.common.executors.CallerThreadExecutor
import com.facebook.common.references.CloseableReference
@ -406,6 +412,23 @@ object ImageUtils {
return modifiedUrl
}
private fun View.findFragment(): Fragment? {
var view: View? = this
val addTagViewList = ArrayList<View>()
while (view != null) {
val tag = view.getTag(androidx.fragment.R.id.fragment_container_view_tag)
if (tag is Fragment) {
addTagViewList.forEach {
it.setTag(androidx.fragment.R.id.fragment_container_view_tag, tag)
}
return tag
}
addTagViewList.add(view)
view = view.parent as? View
}
return null
}
private fun loadImage(
view: SimpleDraweeView?,
highResUrl: String,
@ -414,6 +437,14 @@ object ImageUtils {
shouldNotSaveMemoryCache: Boolean,
controllerListener: BaseControllerListener<ImageInfo>? = null,
) {
val lifecycleObserver = view?.getTag(R.id.lifecycle_observer) as? LifecycleObserver
val lifecycle = if (lifecycleObserver != null) view.findFragment()?.viewLifecycleOwner?.lifecycle else null
lifecycleObserver?.let {
lifecycle?.removeObserver(it)
view.setTag(R.id.lifecycle_observer, null)
}
val listener = getFinalControllerListener(view, controllerListener, lifecycle)
val imageRequest = ImageRequestBuilder.newBuilderWithSource(Uri.parse(highResUrl))
.apply {
if (shouldNotSaveMemoryCache) {
@ -424,7 +455,7 @@ object ImageUtils {
.build()
val controller = Fresco.newDraweeControllerBuilder()
.setImageRequest(imageRequest)
.setControllerListener(controllerListener)
.setControllerListener(listener)
.apply {
if (lowResUrl.isNotEmpty()
&& lowResUrl != highResUrl
@ -443,6 +474,59 @@ object ImageUtils {
view?.setTag(R.string.highResImageTag, highResUrl)
}
private fun getFinalControllerListener(
view: SimpleDraweeView?,
controllerListener: BaseControllerListener<ImageInfo>?,
lifecycle: Lifecycle?
) = object : BaseControllerListener<ImageInfo>() {
override fun onSubmit(id: String?, callerContext: Any?) {
super.onSubmit(id, callerContext)
controllerListener?.onSubmit(id, callerContext)
}
override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
super.onFinalImageSet(id, imageInfo, animatable)
controllerListener?.onFinalImageSet(id, imageInfo, animatable)
animatable?.let {
(lifecycle ?: view?.findFragment()?.viewLifecycleOwner?.lifecycle)?.run {
val observer = object : DefaultLifecycleObserver {
override fun onPause(owner: LifecycleOwner) {
super.onPause(owner)
it.stop()
}
override fun onResume(owner: LifecycleOwner) {
super.onResume(owner)
it.start()
}
override fun onDestroy(owner: LifecycleOwner) {
super.onDestroy(owner)
removeObserver(this)
}
}
view?.setTag(R.id.lifecycle_observer, observer)
addObserver(observer)
}
}
}
override fun onIntermediateImageSet(id: String?, imageInfo: ImageInfo?) {
super.onIntermediateImageSet(id, imageInfo)
controllerListener?.onIntermediateImageSet(id, imageInfo)
}
override fun onIntermediateImageFailed(id: String?, throwable: Throwable?) {
super.onIntermediateImageFailed(id, throwable)
controllerListener?.onIntermediateImageFailed(id, throwable)
}
override fun onFailure(id: String?, throwable: Throwable?) {
super.onFailure(id, throwable)
controllerListener?.onFailure(id, throwable)
}
override fun onRelease(id: String?) {
super.onRelease(id)
controllerListener?.onRelease(id)
}
}
private fun addCachedUrl(url: String) {
imageDecorationThread.execute {
if (url.startsWith("http")) {

View File

@ -26,7 +26,7 @@ object SensorsBridge {
private const val KEY_LAST_PAGE_BUSINESS_ID = "last_page_business_id"
private const val KEY_DOWNLOAD_STATUS = "download_status"
private const val KEY_DOWNLOAD_TYPE = "download_type"
private const val KEY_GAME_SCHEME_TYPE = "game_scheme_type"
private const val KEY_GAME_SCHEMA_TYPE = "game_schema_type"
private const val KEY_GAME_TYPE = "game_type"
const val KEY_POSITION = "position"
const val KEY_TAB_CONTENT = "tab_content"
@ -88,8 +88,6 @@ object SensorsBridge {
private const val KEY_VERIFICATION_TYPE = "verification_type"
private const val KEY_VIDEO_ID = "video_id"
private const val KEY_PLAY_TYPE = "play_type"
private const val KEY_LABEL_NAME = "label_name"
private const val KEY_LABEL_ID = "label_id"
const val KEY_BOTTOM_TAB = "bottom_tab"
const val KEY_MULTI_TAB_NAME = "several_tab_page_name"
const val KEY_MULTI_TAB_ID = "several_tab_page_id"
@ -293,8 +291,6 @@ object SensorsBridge {
private const val EVENT_COLUMN_TEST_CLICK = "ColumnTestClick"
private const val EVENT_SEARCH_DISCOVERY_CLICK = "SearchDiscoveryClick"
private const val EVENT_BYPASS_BROWSING = "BypassBrowsing"
private const val EVENT_FAIL_BYPASS = "FailBypass"
@ -4013,7 +4009,7 @@ object SensorsBridge {
* 触发时机:当下载悬浮窗引导图展示时触发上报
* @param gameId 游戏ID
* @param gameName 游戏名称
* @param gameSchemeType 游戏架构类型64位/32位
* @param gameSchemaType 游戏架构类型64位/32位
* @param downloadStatus 游戏下载状态
* @param gameType 游戏的类型:单机、网游等
* @param downloadType 实际下载方式:本地下载/畅玩下载
@ -4022,7 +4018,7 @@ object SensorsBridge {
fun trackDownloadSuspendedWindowGuideShow(
gameId: String,
gameName: String,
gameSchemeType: String,
gameSchemaType: String,
downloadStatus: String,
gameType: String,
downloadType: String
@ -4030,7 +4026,7 @@ object SensorsBridge {
val json = json {
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
KEY_GAME_SCHEME_TYPE to gameSchemeType
KEY_GAME_SCHEMA_TYPE to gameSchemaType
KEY_DOWNLOAD_STATUS to downloadStatus
KEY_GAME_TYPE to gameType
KEY_DOWNLOAD_TYPE to downloadType
@ -4070,7 +4066,7 @@ object SensorsBridge {
* @param source 来源:游戏下载\重启APP
* @param downloadType 所上报游戏的实际下载方式:本地下载/畅玩下载
* @param downloadStatus 所上报游戏下载状态
* @param gameSchemeType 所上报游戏架构类型64位/32位
* @param gameSchemaType 所上报游戏架构类型64位/32位
* @param gameType 游戏的类型:单机、网游等
* @param gameId 游戏ID
* @param gameName 游戏名称
@ -4079,7 +4075,7 @@ object SensorsBridge {
source: String,
downloadType: String,
downloadStatus: String,
gameSchemeType: String,
gameSchemaType: String,
gameType: String,
gameId: String,
gameName: String
@ -4088,7 +4084,7 @@ object SensorsBridge {
KEY_SOURCE to source
KEY_DOWNLOAD_TYPE to downloadType
KEY_DOWNLOAD_STATUS to downloadStatus
KEY_GAME_SCHEME_TYPE to gameSchemeType
KEY_GAME_SCHEMA_TYPE to gameSchemaType
KEY_GAME_TYPE to gameType
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
@ -4103,7 +4099,7 @@ object SensorsBridge {
* @param source 来源:游戏下载\重启APP
* @param downloadType 所上报游戏的实际下载方式:本地下载/畅玩下载
* @param downloadStatus 所上报游戏下载状态
* @param gameSchemeType 所上报游戏架构类型64位/32位
* @param gameSchemaType 所上报游戏架构类型64位/32位
* @param gameType 游戏的类型:单机、网游等
* @param gameId 游戏ID
* @param gameName 游戏名称
@ -4112,7 +4108,7 @@ object SensorsBridge {
source: String,
downloadType: String,
downloadStatus: String,
gameSchemeType: String,
gameSchemaType: String,
gameType: String,
gameId: String,
gameName: String
@ -4121,7 +4117,7 @@ object SensorsBridge {
KEY_SOURCE to source
KEY_DOWNLOAD_TYPE to downloadType
KEY_DOWNLOAD_STATUS to downloadStatus
KEY_GAME_SCHEME_TYPE to gameSchemeType
KEY_GAME_SCHEMA_TYPE to gameSchemaType
KEY_GAME_TYPE to gameType
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
@ -4135,7 +4131,7 @@ object SensorsBridge {
* 触发时机:触发自动下载提示条展示时上报
* @param downloadType 所上报游戏的实际下载方式:本地下载/畅玩下载
* @param downloadStatus 所上报游戏下载状态
* @param gameSchemeType 所上报游戏架构类型64位/32位
* @param gameSchemaType 所上报游戏架构类型64位/32位
* @param gameType 游戏的类型:单机、网游等
* @param gameId 游戏ID
* @param gameName 游戏名称
@ -4143,7 +4139,7 @@ object SensorsBridge {
fun trackAutomaticInstallationPromptBarShow(
downloadType: String,
downloadStatus: String,
gameSchemeType: String,
gameSchemaType: String,
gameType: String,
gameId: String,
gameName: String
@ -4151,7 +4147,7 @@ object SensorsBridge {
val json = json {
KEY_DOWNLOAD_TYPE to downloadType
KEY_DOWNLOAD_STATUS to downloadStatus
KEY_GAME_SCHEME_TYPE to gameSchemeType
KEY_GAME_SCHEMA_TYPE to gameSchemaType
KEY_GAME_TYPE to gameType
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
@ -4165,7 +4161,7 @@ object SensorsBridge {
* 触发时机:触发自动下载提示条点击时上报
* @param downloadType 所上报游戏的实际下载方式:本地下载/畅玩下载
* @param downloadStatus 所上报游戏下载状态
* @param gameSchemeType 所上报游戏架构类型64位/32位
* @param gameSchemaType 所上报游戏架构类型64位/32位
* @param gameType 游戏的类型:单机、网游等
* @param gameId 游戏ID
* @param gameName 游戏名称
@ -4173,7 +4169,7 @@ object SensorsBridge {
fun trackAutomaticInstallationPromptBarClick(
downloadType: String,
downloadStatus: String,
gameSchemeType: String,
gameSchemaType: String,
gameType: String,
gameId: String,
gameName: String
@ -4181,7 +4177,7 @@ object SensorsBridge {
val json = json {
KEY_DOWNLOAD_TYPE to downloadType
KEY_DOWNLOAD_STATUS to downloadStatus
KEY_GAME_SCHEME_TYPE to gameSchemeType
KEY_GAME_SCHEMA_TYPE to gameSchemaType
KEY_GAME_TYPE to gameType
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
@ -4195,7 +4191,7 @@ object SensorsBridge {
* 触发时机:下载组件展示时上报
* @param gameId 游戏ID
* @param gameName 游戏名称
* @param gameSchemeType 游戏架构类型64位/32位
* @param gameSchemaType 游戏架构类型64位/32位
* @param downloadStatus 所上报游戏下载状态
* @param gameType 游戏的类型:单机、网游等
* @param downloadType 所上报游戏的实际下载方式:本地下载/畅玩下载
@ -4203,7 +4199,7 @@ object SensorsBridge {
fun trackDownloadComponentsShow(
gameId: String,
gameName: String,
gameSchemeType: String,
gameSchemaType: String,
downloadStatus: String,
gameType: String,
downloadType: String,
@ -4211,7 +4207,7 @@ object SensorsBridge {
val json = json {
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
KEY_GAME_SCHEME_TYPE to gameSchemeType
KEY_GAME_SCHEMA_TYPE to gameSchemaType
KEY_DOWNLOAD_STATUS to downloadStatus
KEY_GAME_TYPE to gameType
KEY_DOWNLOAD_TYPE to downloadType
@ -4225,7 +4221,7 @@ object SensorsBridge {
* 触发时机:下载组件点击时上报
* @param gameId 游戏ID
* @param gameName 游戏名称
* @param gameSchemeType 游戏架构类型64位/32位
* @param gameSchemaType 游戏架构类型64位/32位
* @param downloadStatus 所上报游戏下载状态
* @param gameType 游戏的类型:单机、网游等
* @param downloadType 所上报游戏的实际下载方式:本地下载/畅玩下载
@ -4235,7 +4231,7 @@ object SensorsBridge {
fun trackDownloadComponentsContentClick(
gameId: String,
gameName: String,
gameSchemeType: String,
gameSchemaType: String,
downloadStatus: String,
gameType: String,
downloadType: String,
@ -4245,7 +4241,7 @@ object SensorsBridge {
val json = json {
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
KEY_GAME_SCHEME_TYPE to gameSchemeType
KEY_GAME_SCHEMA_TYPE to gameSchemaType
KEY_DOWNLOAD_STATUS to downloadStatus
KEY_GAME_TYPE to gameType
KEY_DOWNLOAD_TYPE to downloadType
@ -4339,31 +4335,6 @@ object SensorsBridge {
trackEvent(EVENT_HALO_SELF_CLICK, json)
}
/**
* 事件IDSearchDiscoveryClick
* 事件名称:搜索发现点击事件
* 触发时机:点击搜索发现时触发
* @param labelName 标签名称
* @param labelId 标签ID
* @param searchContent 搜索内容
* @param position 序号
* @see EVENT_SEARCH_DISCOVERY_CLICK
*/
fun trackSearchDiscoveryClick(
labelName: String,
labelId: String,
searchContent: String,
position: Int
) {
val json = json {
KEY_LABEL_NAME to labelName
KEY_LABEL_ID to labelId
KEY_SEARCH_CONTENT to searchContent
KEY_POSITION to position
}
trackEvent(EVENT_SEARCH_DISCOVERY_CLICK, json)
}
/**
* 事件IDBypassBrowsing
* 事件名称:分流器访问事件

View File

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="root_container" type="id" />
<item name="lifecycle_observer" type="id" />
</resources>

View File

@ -58,6 +58,7 @@ dependencies {
api "com.jakewharton.rxbinding2:rxbinding:${rxBinding2}"
api "com.github.tbruyelle:rxpermissions:${rxPermissions}"
api "com.squareup.okhttp3:okhttp:${okHttp}"
api "com.squareup.okhttp3:okhttp-brotli:${okHttp}"
api "com.squareup.retrofit2:retrofit:${retrofit}"
api "com.squareup.retrofit2:converter-gson:${retrofit}" // include gson 2.7
api "com.squareup.retrofit2:adapter-rxjava2:${retrofit}"

View File

@ -15,8 +15,6 @@ interface ILoginProvider : IProvider {
callback: () -> Unit
)
fun createLoggingDialog(context: Context): Dialog
fun createQuickLoginBackgroundView(context: Context): View
fun startQuickLoginHelperPageFromQuickLogin(loginToken: String, context: Context, callback: (() -> Unit)?)

View File

@ -6,6 +6,8 @@ import android.text.TextUtils;
import androidx.annotation.Nullable;
import java.io.BufferedReader;
import java.io.FileReader;
import java.lang.reflect.Method;
public class ProcessUtil {
@ -20,13 +22,25 @@ public class ProcessUtil {
return currentProcessName;
}
//1)通过Application的API获取当前进程名
//0)通过反射 ActivityThread 获取实例再获取当前进程名
currentProcessName = getCurrentProcessNameByActivityThreadInstance();
if (!TextUtils.isEmpty(currentProcessName)) {
return currentProcessName;
}
//1)通过 CMD 获取当前进程名
currentProcessName = getCurrentProcessNameByCMD(android.os.Process.myPid());
if (!TextUtils.isEmpty(currentProcessName)) {
return currentProcessName;
}
//2)通过 Application 的 API 获取当前进程名
currentProcessName = getCurrentProcessNameByApplication();
if (!TextUtils.isEmpty(currentProcessName)) {
return currentProcessName;
}
//2)通过反射ActivityThread获取当前进程名
//3)通过反射 ActivityThread 获取当前进程名
currentProcessName = getCurrentProcessNameByActivityThread();
if (!TextUtils.isEmpty(currentProcessName)) {
return currentProcessName;
@ -38,7 +52,7 @@ public class ProcessUtil {
/**
* 通过Application新的API获取进程名无需反射无需IPC效率最高。
*/
public static String getCurrentProcessNameByApplication() {
private static String getCurrentProcessNameByApplication() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
return Application.getProcessName();
}
@ -48,7 +62,7 @@ public class ProcessUtil {
/**
* 通过反射ActivityThread获取进程名避免了ipc
*/
public static String getCurrentProcessNameByActivityThread() {
private static String getCurrentProcessNameByActivityThread() {
String processName = null;
try {
final Method declaredMethod = Class.forName("android.app.ActivityThread", false, Application.class.getClassLoader())
@ -64,4 +78,52 @@ public class ProcessUtil {
return processName;
}
private static String getCurrentProcessNameByActivityThreadInstance() {
try {
// Get ActivityThread class
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread",false, Application.class.getClassLoader());
// Get the current ActivityThread instance
Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
currentActivityThreadMethod.setAccessible(true);
Object activityThread = currentActivityThreadMethod.invoke(null);
// Get the getProcessName method
Method getProcessNameMethod = activityThreadClass.getDeclaredMethod("getProcessName");
getProcessNameMethod.setAccessible(true);
// Call the getProcessName method
return (String) getProcessNameMethod.invoke(activityThread);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private static String getCurrentProcessNameByCMD(int pid) {
//get from /proc/PID/cmdline
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("/proc/" + pid + "/cmdline"));
String processName = br.readLine();
if (!TextUtils.isEmpty(processName)) {
processName = processName.trim();
if (!TextUtils.isEmpty(processName)) {
return processName; //OK
}
}
} catch (Exception ignored) {
} finally {
try {
if (br != null) {
br.close();
}
} catch (Exception ignored) {
}
}
//failed
return null;
}
}

View File

@ -1,22 +0,0 @@
package com.gh.gamecenter.feature.entity
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
import kotlinx.parcelize.Parcelize
@Parcelize
class DiscoveryTagEntity(
@SerializedName("_id")
var id: String? = "",
var text: String? = "",
@SerializedName("keyword")
var _keyword: String? = ""
) : Parcelable {
val keyword get(): String {
val keyword = this._keyword
if (keyword.isNullOrEmpty()) {
return text ?: ""
}
return keyword
}
}

View File

@ -70,8 +70,6 @@ class SettingsEntity(
var hotSearch: List<HotSearch>? = listOf(),
@SerializedName("tag")
var hotTag: List<HotTagEntity>? = listOf(),
@SerializedName("discover_tag")
var discoveryTag: List<DiscoveryTagEntity>? = listOf(),
@SerializedName("hot_list")
var rankList: List<RankList>? = listOf(),
@SerializedName("wechat_game_search_list")

View File

@ -33,18 +33,6 @@ class LoginProviderImpl : ILoginProvider {
}
}
override fun createLoggingDialog(context: Context) =
Dialog(context, com.gh.gamecenter.common.R.style.DialogWindowTransparent).apply {
val binding = SetWaitDialogBinding.inflate(LayoutInflater.from(context)).apply {
root.background = com.gh.gamecenter.common.R.drawable.background_shape_white_radius_8.toDrawable(context)
setWaitMessage.setTextColor(com.gh.gamecenter.common.R.color.text_primary.toColor(context))
setWaitMessage.text = R.string.logging.toResString()
}
requestWindowFeature(Window.FEATURE_NO_TITLE)
setContentView(binding.root)
setCanceledOnTouchOutside(false)
}
override fun createQuickLoginBackgroundView(context: Context): View =
LayoutQuickLoginBackgroundBinding.inflate(LayoutInflater.from(context)).root

View File

@ -75,10 +75,10 @@ class QuickLoginHelperActivity : BaseActivity(), LoginHelper.LoginCallback, Obse
private fun login(content: JSONObject, loginTag: LoginTag) {
val logUtils = ARouter.getInstance().build(RouteConsts.provider.logUtils).navigation() as? ILogUtilsProvider
logUtils?.login("logging", loginTag.name, mEntrance)
if (loginTag != LoginTag.oauth) {
mLoginDialog = WaitingDialogFragment.newInstance(getString(R.string.logging))
mLoginDialog?.show(supportFragmentManager, null)
}
mLoginDialog = WaitingDialogFragment.newInstance(getString(R.string.logging))
mLoginDialog?.show(supportFragmentManager, null)
mUserViewModel.login(content, loginTag)
}

View File

@ -19,7 +19,9 @@ import io.reactivex.ObservableEmitter
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody
import org.json.JSONObject
import retrofit2.HttpException
@ -142,7 +144,7 @@ class MessageListViewModel(application: Application, private val mType: String,
// 后端同步
val jsonObject = JSONObject()
jsonObject.put("type", "system_message")
val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
val body = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
mApi.postMessageRead(UserManager.getInstance().userId, messageId, body)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())

View File

@ -158,7 +158,7 @@ class NetworkDiagnosisActivity : ToolBarActivity() {
builder.append(response.toString())
builder.append("\n")
builder.append("Response Header:\n")
builder.append(response.headers().toString())
builder.append(response.headers.toString())
builder.append("\n")
} catch (e: IOException) {
builder.append("Error:\n")

View File

@ -16,7 +16,9 @@ import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody
import org.json.JSONObject
import retrofit2.HttpException
@ -37,7 +39,7 @@ class BindPhoneViewModel(application: Application) : AndroidViewModel(applicatio
params["mobile"] = phoneNum
val jsonObject = JSONObject(params as Map<*, *>)
jsonObject.put("device", device)
val body: RequestBody = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
val body: RequestBody = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
api.bindPhone(1, body)
.subscribeOn(Schedulers.io())
@ -88,7 +90,7 @@ class BindPhoneViewModel(application: Application) : AndroidViewModel(applicatio
}
val jsonObject = JSONObject(params as Map<*, *>)
jsonObject.put("device", device)
val body: RequestBody = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
val body: RequestBody = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
api.bindPhone(2, body)
.subscribeOn(Schedulers.io())
@ -132,7 +134,7 @@ class BindPhoneViewModel(application: Application) : AndroidViewModel(applicatio
params["mobile"] = phoneNum
val jsonObject = JSONObject(params as Map<*, *>)
jsonObject.put("device", device)
val body: RequestBody = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
val body: RequestBody = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
api.reBindPhone(1, body)
.subscribeOn(Schedulers.io())
@ -184,7 +186,7 @@ class BindPhoneViewModel(application: Application) : AndroidViewModel(applicatio
}
val jsonObject = JSONObject(params as Map<*, *>)
jsonObject.put("device", device)
val body: RequestBody = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString())
val body: RequestBody = jsonObject.toString().toRequestBody("application/json".toMediaTypeOrNull())
api.reBindPhone(2, body)
.subscribeOn(Schedulers.io())

View File

@ -7,7 +7,7 @@ plugins {
android {
// 在 DEFAULT_PLUGIN_URL 中提取插件版本号
def defaultPluginUrl = "https://dev-app-static.796697.com/va/plugin/2024/09/02/1.0.3_64_1725265812586.zip"
def defaultPluginUrl = "https://app-static.796697.com/va/plugin/2024/10/17/1.0.3_64_1729148903919.zip"
def versionText = defaultPluginUrl.substring(defaultPluginUrl.lastIndexOf("/") + 1)
def pluginVersionPattern = ~/^\d+.\d+.\d+/
def matcher = versionText =~ pluginVersionPattern

2
vasdk

Submodule vasdk updated: a13dc8061e...473be43ac0