Compare commits

..

66 Commits

Author SHA1 Message Date
5880950f11 refactor: update vasdk commit id. 2024-03-16 17:58:38 +08:00
e6befb7d94 feat: 理论上来讲光环的业务不需要在游戏进程初始化的。防止游戏进程被占用过多的地址空间。 2024-03-16 17:47:48 +08:00
c7104ef959 refactor: remove build/plugin assets dir. 2024-03-16 17:17:53 +08:00
9d7c871ace refactor: dont include cw32 & plugin modules 2024-03-16 17:08:20 +08:00
06a3862a37 refactor: remove some module dependencies 2024-03-16 17:02:28 +08:00
5cd6324b07 feat: 一体化的云存档登录 2024-03-15 10:42:12 +08:00
75b279bc0d feat: revert commit. 2024-03-14 09:54:22 +08:00
bd934c092a fix: debug variant cannot use plugin files from server. 2024-03-13 11:46:40 +08:00
a4ac02ddbc fix: remove test code from product code. 2024-03-13 10:10:15 +08:00
db84dc0722 fix: remove test condition 2024-03-12 16:35:46 +08:00
06260a2ae3 refactor: update commit id. 2024-03-12 16:32:36 +08:00
f7972046e7 refactor: update commit id. 2024-03-12 16:00:53 +08:00
b5f1634b19 feat: 合并部分云存档代码 2024-03-12 09:59:48 +08:00
e8e629028b refactor: update vasdk 2024-03-11 10:27:07 +08:00
3f2d0a4db4 refactor: update vasdk commit id. 2024-03-06 14:30:59 +08:00
057590e1d0 refactor: update vasdk commit id. 2024-03-06 13:55:00 +08:00
bcd46e45e2 fix: 谷歌框架安装区分旧版还是新版畅玩组件 2024-03-05 15:01:04 +08:00
1a268eb02f fix: 优化部分启动逻辑&修复个别游戏因为安装架构选择导致黑屏无法启动 2024-03-05 14:35:32 +08:00
6beb746f21 fix: update meta_build.sh 2024-03-04 14:41:56 +08:00
34fafcdfa0 feat: agp 7.1.3 gradle打包产物位置有变更,考虑到插件更新逻辑已变更,不需要在编译光环助手时同步编译插件了,所以修改为手动编译插件,再copy到build/plugin目录 2024-03-01 17:28:51 +08:00
4d2606cc83 refactor: update submodule commit id 2024-03-01 15:19:15 +08:00
8f908b54c7 refactor: update submodule commit id 2024-03-01 14:49:13 +08:00
7af085df34 refactor: update ndownload commit id 2024-03-01 11:01:38 +08:00
00bdb0a3cc refactor: update vasdk commit id. 2024-03-01 10:56:36 +08:00
0d329a19b0 refactor: update vasdk commit id. 2024-03-01 10:56:36 +08:00
2edbfc505c feat: 32位组件安装插件 2024-03-01 10:56:36 +08:00
ee8748a954 refactor: update version 2024-03-01 10:56:36 +08:00
3bdd419183 fix: 插件更新逻辑 2024-03-01 10:56:36 +08:00
7c8c3a4679 refactor: update vasdk commit id. 2024-03-01 10:56:36 +08:00
8fc5be0e51 feat: 添加更新按钮。 2024-03-01 10:56:36 +08:00
6cc73d4b05 fix:修复一体化,畅玩游戏启动判断 2024-03-01 10:56:36 +08:00
fe6405fac3 fix: 修复卸载apk不生效 2024-03-01 10:56:36 +08:00
88dd3ea5ec fix:新旧版本畅玩组件isInstalled语义错误 2024-03-01 10:56:36 +08:00
0641761143 fix:新旧版本畅玩组件isInstalled语义错误 2024-03-01 10:56:36 +08:00
5adde797e1 fix:畅玩游戏无法更新的问题 2024-03-01 10:56:36 +08:00
7c346c632c refactor: update vasdk commit id 2024-03-01 10:56:35 +08:00
17b7101912 refactor: update vasdk commit id 2024-03-01 10:56:35 +08:00
7e1cafee4b refactor: update commit id 2024-03-01 10:56:35 +08:00
03df8e1012 feat: 32位组件更新下载 2024-03-01 10:56:35 +08:00
bb66f4af06 refactor!: 添加测试环境的脚本 2024-03-01 10:56:35 +08:00
6b1e92ee3d refactor!: 添加测试环境的脚本 2024-03-01 10:56:35 +08:00
ec1c92cfe0 feat: new/upgrade接口参数修改 2024-03-01 10:56:35 +08:00
89b85b115e feat: 畅玩32位和插件的更新流程 2024-03-01 10:56:35 +08:00
d4e2788d8d refactor!: 临时修改打包测试版本 2024-03-01 10:55:43 +08:00
865903d0da refactor: 优化畅玩32 debug打包步骤 2024-03-01 10:55:43 +08:00
3afebb1e38 feat: 获取32位组件和插件的接口数据 2024-03-01 10:55:43 +08:00
feab4f4f76 refactor: update commit id 2024-03-01 10:55:43 +08:00
4054f66b4b feat: 修改va配置读取 2024-03-01 10:55:43 +08:00
b5ee2679e9 feat: 修改plugin配置读取 2024-03-01 10:55:43 +08:00
c060480b23 fix: 修复头条,快手等其他flavor脚本打包出错的问题 2024-03-01 10:55:37 +08:00
26f09057ba refactor: upgrade shadow_version to 1.0.4 2024-03-01 10:53:48 +08:00
b1457f795d refactor: update vasdk commit id. 2024-03-01 10:53:48 +08:00
193e4487c9 fix: min sdk version smaller than 21. 2024-03-01 10:53:48 +08:00
32bff3836e refactor: 更新shadow版本至 1.0.3 2024-03-01 10:53:48 +08:00
64c35e9181 refactor: 更新maven拉取顺序 2024-03-01 10:53:48 +08:00
63783e374d refactor: 更新apk文件路径 2024-03-01 10:53:46 +08:00
020222a451 refactor: 下载插件到assets目录 2024-03-01 10:52:04 +08:00
15df636967 refactor: 更新打包脚本 2024-03-01 10:52:01 +08:00
aaa552ffdc feat: 展示64位va插件版本信息 https://jira.shanqu.cc/browse/GHZS-3885 2024-03-01 10:46:44 +08:00
9a372ba269 fix: 过滤va项目的配置&修复错误的assets添加脚步 2024-03-01 10:44:56 +08:00
56383b2938 feat: 光环助手va组件兼容旧版畅玩助手游戏业务 2024-03-01 10:44:56 +08:00
c6f161999d feat: 接入vasdk编译通过 2024-03-01 10:44:56 +08:00
d796739b3c refactor: va模块引用 2024-03-01 10:44:54 +08:00
922c8e5cde feat: 加速器模块占用空间太大,给ci/cd集成增加时间成本,考虑到加速器变更频繁度较低,改为maven引用 2024-03-01 10:43:00 +08:00
e0611ebfca feat: 同步vasdk的代码 2024-03-01 10:43:00 +08:00
fed1f7b90f feat: 接入va模块 2024-03-01 10:42:58 +08:00
1012 changed files with 20116 additions and 44492 deletions

View File

@ -71,7 +71,7 @@ android_build:
exit_codes: 137
only:
- dev
- feat/GHZSCY-5250
- dev-5.33.0
# 代码检查
sonarqube_analysis:
@ -102,7 +102,7 @@ sonarqube_analysis:
exit_codes: 137
only:
- dev
- release
- dev-5.33.0
## 发送简易检测结果报告
send_sonar_report:
@ -120,7 +120,7 @@ send_sonar_report:
exit_codes: 137
only:
- dev
- release
- dev-5.33.0
oss-upload&send-email:
tags:
@ -152,4 +152,4 @@ oss-upload&send-email:
- /usr/local/bin/python /ci-android-mail-jira-comment.py
only:
- dev
- feat/GHZSCY-5250
- dev-5.33.0

6
.gitmodules vendored
View File

@ -5,6 +5,12 @@
[submodule "vspace-bridge"]
path = vspace-bridge
url = ../../../cwzs/android/vspace-bridge.git
[submodule "module_common/src/debug/assets/assistant-android-mock"]
path = module_common/src/debug/assets/assistant-android-mock
url = ../../../halo/android/assistant-android-mock.git
[submodule "ndownload"]
path = ndownload
url = ../../../android/ndownload.git
[submodule "vasdk"]
path = vasdk
url = ../../../sdg/android/vasdk.git

View File

@ -23,8 +23,6 @@ android {
}
compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
@ -75,7 +73,7 @@ android {
versionName rootProject.ext.versionName
applicationId rootProject.ext.applicationId
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt', 'proguard-fresco.txt'
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt', 'proguard-fresco.txt', rootProject.ext.va_proguard_rules
String CORE_EVENT_GAME_CATEGORY = ""
@ -194,7 +192,8 @@ android {
// internal 内部测试包使用的 flavor接口包含包括测试和正式环境
internal {
dimension "env"
versionNameSuffix "-debug"
// blame_yangfei: test script lines
//versionNameSuffix "-debug"
buildConfigField "String", "DEV_API_HOST", "\"${DEV_API_HOST}\""
buildConfigField "String", "NEW_DEV_API_HOST", "\"${NEW_DEV_API_HOST}\""
@ -310,6 +309,7 @@ dependencies {
// debugImplementation "com.gu.android:toolargetool:${toolargetool}" // 需要使用调试时才启用
debugImplementation "com.github.nichbar:WhatTheStack:${whatTheStack}"
// debugImplementation "io.github.didi.dokit:dokitx:${dokit}"
implementation "androidx.multidex:multidex:${multiDex}"
implementation "androidx.fragment:fragment-ktx:${fragment}"
@ -321,8 +321,7 @@ dependencies {
implementation "com.kyleduo.switchbutton:library:${switchButton}"
implementation "com.tencent.vasdolly:helper:${apkChannelPackage}"
implementation "com.tencent.vasdolly:writer:${apkChannelPackage}"
implementation "com.leon.channel:helper:${apkChannelPackage}"
implementation "com.j256.ormlite:ormlite-android:${ormlite}"
implementation "com.j256.ormlite:ormlite-core:${ormlite}"
@ -345,6 +344,8 @@ dependencies {
})
implementation "com.github.CarGuo.GSYVideoPlayer:gsyVideoPlayer-exo_player2:$gsyVideo"
// implementation "androidx.work:work-runtime:${workManager}"
implementation "com.llew.huawei:verifier:${verifier}"
teaImplementation "com.bytedance.applog:RangersAppLog-Lite-cn:${bytedanceApplog}"
@ -357,20 +358,20 @@ dependencies {
implementation "com.lg:easyfloat:${easyFloat}"
implementation "io.github.florent37:shapeofview:${shapeOfView}"
implementation "com.lg:apksig:${apksig}"
implementation "com.lg:gid:${gid}"
implementation "com.lg:shortcut:${shortcut}"
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:${desugarJdkLibs}"
kapt "com.alibaba:arouter-compiler:$arouterVersion"
implementation project(':ndownload')
implementation project(':vspace-bridge:vspace')
implementation project(':vspace-bridge')
implementation (project(':module_common')) {
implementation(project(':module_common')) {
exclude group: 'androidx.swiperefreshlayout'
}
implementation(project(':module_login')) {
@ -408,13 +409,15 @@ dependencies {
exclude group: 'androidx.swiperefreshlayout'
}
internalImplementation(project(':module_internal_test'))
// 根据BUILD_PUSH_TYPE决定使用哪个推送SDK目前默认使用阿里云推送
def pushProject = findProperty('BUILD_PUSH_TYPE') == 'jg'
? project(':feature:jg_push') : project(':feature:acloud_push')
implementation(pushProject) {
implementation(project(":va-lib"))
implementation(project(':va-main')) {
exclude group: 'androidx.swiperefreshlayout'
}
debugImplementation "com.bytedance.tools.codelocator:codelocator-core:2.0.3"
compileOnly project(":va-core")
compileOnly project(":va-plugin-host-lib")
implementation project(":va-plugin-host")
implementation project(":va-archive")
}
File propFile = file('sign.properties')
@ -485,13 +488,6 @@ andResGuard {
// 打开这个开关会合并所有哈希值相同的资源,但请不要过度依赖这个功能去除去冗余资源
mergeDuplicatedRes = true
whiteList = [
"R.xml.jpush*",
"R.drawable.jpush*",
"R.layout.jpush*",
"R.layout.push*",
"R.string.jg*",
"R.style.MyDialogStyle",
"R.style.JPushTheme",
"R.drawable.icon",
"R.drawable.ic_bar_back",
"R.drawable.toolbar_search_icon",

View File

@ -80,6 +80,9 @@
### EasyFloat
-keep class com.lzf.easyfloat.* {*;}
### dokit
-keep class com.didichuxing.** {*;}
### 广点通SDK
-dontwarn com.qq.gdt.action.**
-keep class com.qq.gdt.action.** {*;}

View File

@ -8,7 +8,7 @@ import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.PackageFlavorHelper
import com.gh.gamecenter.core.provider.IFlavorProvider
import com.gh.gamecenter.core.utils.SPUtils
import com.tencent.vasdolly.helper.ChannelReaderUtil
import com.leon.channel.helper.ChannelReaderUtil
class FlavorProviderImp : IFlavorProvider {
override fun getChannelStr(application: Application): String {

View File

@ -8,7 +8,7 @@ import com.gh.gamecenter.core.provider.IFlavorProvider
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.TimeUtils
import com.halo.assistant.HaloApp
import com.tencent.vasdolly.helper.ChannelReaderUtil
import com.leon.channel.helper.ChannelReaderUtil
class FlavorProviderImp : IFlavorProvider {

View File

@ -6,27 +6,70 @@ import android.view.View
import android.view.ViewGroup
import androidx.annotation.Keep
import com.gh.gamecenter.R
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.databinding.LayoutPersonalOtherItemBinding
import com.gh.vspace.installexternalgames.InstallExternalGameActivity
import com.lg.vspace.VaApp
import com.lg.vspace.plugin.host.PluginHelper
import com.lightgame.utils.Utils
import com.lightgame.utils.toast.ToastHelper
import java.io.File
@Keep
class ExternalGameUsage : IExternalGamesUsage {
override fun addInstallExternalGameButton(viewParent: ViewGroup) {
class ExternalGameUsage : ITestCase {
private fun buttonTemplate(viewParent: ViewGroup, id: Int, fn: (LayoutPersonalOtherItemBinding) -> Unit) {
val context = viewParent.context
viewParent.findViewById<View>(R.id.install_game_from_external) ?: run {
viewParent.findViewById<View>(id) ?: run {
val binding = LayoutPersonalOtherItemBinding.inflate(LayoutInflater.from(context)).apply {
root.id = R.id.install_game_from_external
titleTv.text = context.getString(R.string.title_install_external_game)
iconIv.setImageResource(R.drawable.ic_personal_my_game)
root.setOnClickListener {
VHelper.connectService {
context.startActivity(
InstallExternalGameActivity.getIntent(context)
.apply { flags = flags or Intent.FLAG_ACTIVITY_NEW_TASK })
}
}
root.id = id
fn(this)
}
viewParent.addView(binding.root, 0)
}
}
override fun addInstallExternalGameButton(viewParent: ViewGroup) {
val context = viewParent.context
buttonTemplate(viewParent, R.id.install_game_from_external) {
it.titleTv.text = context.getString(R.string.title_install_external_game)
it.iconIv.setImageResource(R.drawable.ic_personal_my_game)
it.root.setOnClickListener {
VHelper.connectService {
context.startActivity(
InstallExternalGameActivity.getIntent(context).apply { flags = flags or Intent.FLAG_ACTIVITY_NEW_TASK })
}
}
}
}
override fun addInstallPluginButton(viewParent: ViewGroup) {
buttonTemplate(viewParent, R.id.install_plugin) {
it.titleTv.text = "安装64位插件"
it.root.setOnClickListener {
val file = File("/data/local/tmp/gh-plugins/artifacts.zip")
if (file.exists()) {
Utils.log(VHelper.LOG_TAG, "有本地更新文件: 64位插件")
PluginHelper.getInstance().updatePlugin(file)
} else {
ToastUtils.showToast("data/local/tmp没有push文件")
}
}
}
}
override fun addInstallPlugin32Button(viewParent: ViewGroup) {
buttonTemplate(viewParent, R.id.install_plugin_32) {
it.titleTv.text = "安装32位插件"
it.root.setOnClickListener {
val file = File("/data/local/tmp/gh-plugins/artifacts32.zip")
if (file.exists()) {
Utils.log(VHelper.LOG_TAG, "有本地更新文件: 32位插件")
VaApp.get().appManager.updatePlugin(file.absolutePath, "artifacts32.zip")
} else {
ToastUtils.showToast("data/local/tmp没有push文件")
}
}
}
}
}

View File

@ -25,6 +25,11 @@ class ExternalGameAdapter(private val games: List<ExternalGameUiState>, private
路径:${item.apkPath}
""".trimIndent()
}
holder.update.setOnClickListener {
onItemClickListener.onItemClick(item, OnItemClickListener.ClickType.CLICK_INSTALL)
}
holder.install.goneIf(item.isInstalled) {
holder.install.setOnClickListener {
onItemClickListener.onItemClick(item, OnItemClickListener.ClickType.CLICK_INSTALL)

View File

@ -8,4 +8,5 @@ class ExternalGameViewHolder(binding: LayoutExternalGameItemBinding) : RecyclerV
val install = binding.btnInstall
val uninstall = binding.btnUninstall
val start = binding.btnStart
val update = binding.btnUpdate
}

View File

@ -16,6 +16,7 @@ import com.gh.gamecenter.databinding.FragmentInstallExternalGamesBinding
import com.gh.vspace.VHelper
import com.halo.assistant.HaloApp
import com.lg.vspace.VirtualAppManager
import com.lightgame.download.DownloadEntity
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
@ -105,6 +106,15 @@ class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
private fun install(externalGameUiState: ExternalGameUiState) {
val bit =
externalGameUiState.externalGameEntity.cpuAbi.let { if (it.size == 1 && it.contains("armeabi-v7a")) "32" else "64" }
VHelper.install(requireContext(), DownloadEntity().apply {
externalGameUiState.externalGameEntity.apply {
packageName = apkPackageName
path = apkPath
}
}, true)
if (VHelper.showDialogIfVSpaceIsNeeded(
requireContext(),
"",

View File

@ -24,6 +24,14 @@
android:visibility="gone"
tools:visibility="visible" />
<Button
android:id="@+id/btn_update"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/text_update"
android:visibility="visible"
tools:visibility="visible" />
<Button
android:id="@+id/btn_uninstall"
android:layout_width="wrap_content"

View File

@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="install_game_from_external" type="id" />
<item name="install_plugin" type="id" />
<item name="install_plugin_32" type="id" />
</resources>

View File

@ -2,6 +2,7 @@
<resources>
<string name="title_install_external_game">从SD卡安装</string>
<string name="text_install">安装</string>
<string name="text_update">更新</string>
<string name="text_uninstall">卸载</string>
<string name="text_start">启动</string>
</resources>

View File

@ -12,7 +12,7 @@ import com.gh.gamecenter.core.utils.TimeUtils
import com.gh.gamecenter.core.utils.ToastUtils
import com.halo.assistant.HaloApp
import com.kwai.monitor.payload.TurboHelper
import com.tencent.vasdolly.helper.ChannelReaderUtil
import com.leon.channel.helper.ChannelReaderUtil
class FlavorProviderImp : IFlavorProvider {

View File

@ -11,14 +11,6 @@
<package android:name="com.lg.vspace" />
</queries>
<!-- 华为/荣耀角标 -->
<uses-permission android:name="com.huawei.android.launcher.permission.CHANGE_BADGE "/>
<uses-permission android:name="com.hihonor.android.launcher.permission.CHANGE_BADGE" />
<!-- vivo角标 -->
<uses-permission android:name="com.vivo.notification.permission.BADGE_ICON" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<!-- 允许应用程序访问网络连接 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 允许应用程序写入外部存储如SD卡上写文件 -->
@ -92,7 +84,30 @@
com.tencent.qqmini,
com.tencent.qqmini.minigame.external,
com.tencent.qqmini.minigame.opensdk,
com.tencent.qqmini.union.ad" />
com.tencent.qqmini.union.ad,
com.lg.vspace,
io.lg.va.common,
com.va.floating,
com.lg.cloud,
com.lg.archive,
com.lg.vclient,
com.va.realname,
com.lg.vspace.flavor,
com.lg.update,
com.lg.login,
com.lg.accelerator,
com.lody.virtual,
com.lg.core,
com.lg.ads,
com.lg.common,
com.lg.vspace.network,
com.lody.virtual.lib.res,
com.va.host,
com.lg.vspace.plugin.host,
com.lg.plugin.constant,
com.bytedance.tools.codelocator,
org.chickenhook.restrictionbypass,
com.lody.virtual.sandhook,com.lg.vspace.common" />
<!-- 去掉 SDK 一些流氓权限 -->
<uses-permission
@ -107,9 +122,8 @@
android:name="android.permission.GET_TASKS"
tools:node="remove" />
<uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION"
tools:node="remove" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"
tools:node="remove"/>
<supports-screens
android:anyDensity="true"
@ -126,12 +140,10 @@
android:label="@string/app_name"
android:largeHeap="true"
android:networkSecurityConfig="@xml/network_security_config"
android:preserveLegacyExternalStorage="true"
android:requestLegacyExternalStorage="true"
android:resizeableActivity="true"
android:theme="@style/AppCompatTheme.APP"
tools:replace="android:name,android:allowBackup"
tools:targetApi="r">
tools:targetApi="n">
<meta-data
android:name="EasyGoClient"
@ -204,7 +216,7 @@
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.newsdetail.NewsDetailActivity"
android:name="com.gh.gamecenter.NewsDetailActivity"
android:screenOrientation="portrait" />
<activity
@ -259,7 +271,7 @@
android:windowSoftInputMode="stateHidden" />
<activity
android:name="com.gh.gamecenter.libao.LibaoDetailActivity"
android:name="com.gh.gamecenter.LibaoDetailActivity"
android:screenOrientation="portrait" />
<activity
@ -323,6 +335,14 @@
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden" />
<activity
android:name="com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qa.answer.edit.AnswerEditActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.InfoActivity"
android:screenOrientation="portrait" />
@ -331,6 +351,10 @@
android:name=".qa.questions.invite.QuestionsInviteActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qa.myqa.MyAskActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qa.questions.edit.QuestionEditActivity"
android:screenOrientation="portrait" />
@ -368,6 +392,10 @@
android:name="com.gh.gamecenter.qa.article.edit.ArticleEditActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qa.article.MyArticleActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.qa.article.draft.ArticleDraftActivity"
android:screenOrientation="portrait" />
@ -406,6 +434,10 @@
android:name="com.gh.gamecenter.history.HistoryActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.personalhome.rating.RatingActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.gamedetail.rating.logs.CommentLogsActivity"
android:screenOrientation="portrait" />
@ -478,6 +510,9 @@
android:name=".gamedetail.fuli.kaifu.ServersSubscribedGameListActivity"
android:screenOrientation="portrait" />
<activity
android:name=".qa.answer.draft.AnswerDraftActivity"
android:screenOrientation="portrait" />
<activity
android:name=".gamedetail.rating.RatingFoldActivity"
android:screenOrientation="portrait" />
@ -489,6 +524,10 @@
android:name=".video.poster.PosterEditActivity"
android:screenOrientation="portrait" />
<activity
android:name=".video.poster.PosterClipActivity"
android:screenOrientation="portrait" />
<activity
android:name=".forum.detail.ForumDetailActivity"
android:screenOrientation="portrait" />
@ -594,10 +633,6 @@
android:name=".game.commoncollection.detail.CommonCollectionDetailActivity"
android:screenOrientation="portrait" />
<activity
android:name=".game.commoncollection.detail.CustomCommonCollectionDetailActivity"
android:screenOrientation="portrait" />
<activity
android:name=".gamecollection.detail.GameCollectionDetailActivity"
android:screenOrientation="portrait" />
@ -689,7 +724,7 @@
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.toolbox.ToolBoxActivity"
android:name="com.gh.gamecenter.toolbox.ToolBoxBlockActivity"
android:screenOrientation="portrait" />
<activity
@ -766,12 +801,6 @@
android:name="com.gh.gamecenter.SplashAdActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.gh.gamecenter.wrapper.ToolbarWrapperActivity"
android:screenOrientation="portrait" />
<activity android:name=".forum.home.CommunityActivity"
android:screenOrientation="portrait"/>
<!-- <activity-->
<!-- android:name="${applicationId}.douyinapi.DouYinEntryActivity"-->
@ -783,7 +812,8 @@
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}"
android:exported="false"
android:grantUriPermissions="true">
android:grantUriPermissions="true"
tools:replace="android:authorities">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
@ -827,7 +857,7 @@
<!-- tools:node="remove" />-->
<!-- </provider>-->
<service android:name="com.gh.gamecenter.install.InstallService" />
<service android:name = "com.gh.gamecenter.install.InstallService" />
<receiver
android:name="com.gh.gamecenter.receiver.DownloadReceiver"
@ -846,8 +876,8 @@
<activity
android:name="com.gh.common.xapk.XapkInstallReceiver"
android:exported="false"
android:theme="@style/Theme.Transparent" />
android:theme="@style/Theme.Transparent"
android:exported="false" />
<receiver
android:name="com.gh.gamecenter.receiver.ActivitySkipReceiver"
@ -856,6 +886,7 @@
<action android:name="com.gh.gamecenter.ACTIVITYSKIP" />
</intent-filter>
</receiver>
</application>
</manifest>

View File

@ -6,6 +6,8 @@
<link rel="stylesheet" type="text/css" href="normalize.css">
<link rel="stylesheet" type="text/css" href="style.css">
<link rel="stylesheet" type="text/css" href="video-js.min.css">
<!-- <link rel="stylesheet" href="https://static-web.ghzs.com/website-static/lib/video-js.min.css">--> <!--在web页面播放视频-->
<!--<link rel="stylesheet" type="text/css" href="https://resource.ghzs.com/css/halo_app.css">-->
</head>
<body style="overflow-x: hidden; word-break: break-all;">
@ -13,5 +15,8 @@
<script type="text/javascript" src="zepto.min.js"></script>
<script type="text/javascript" src="rich_editor.js"></script>
<script type="text/javascript" src="video.min.js"></script>
<!--<script src="https://static-web.ghzs.com/website-static/lib/video.min.js"></script>--> <!--在web页面播放视频-->
<!--<script type="text/javascript" src="content.js"></script>-->
<!--<script type="text/javascript" src="https://resource.ghzs.com/js/halo_app.js"></script>-->
</body>
</html>

View File

@ -1 +0,0 @@
{"v":"5.12.2","fr":60,"ip":0,"op":40,"w":66,"h":66,"nm":"icon_tab_my","ddd":0,"assets":[{"id":"comp_0","nm":"icon","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"highlight","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33.134,34.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":0.733},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,-0.004],[0.493,0],[0,0.004],[-0.493,0]],"o":[[0,0.004],[-0.493,0],[0,-0.004],[0.493,0]],"v":[[0.893,1.488],[0,1.496],[-0.893,1.488],[0,1.483]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0.267},"t":10,"s":[{"i":[[0,-1.018],[1.793,0],[0,1.018],[-1.793,0]],"o":[[0,1.018],[-1.793,0],[0,-1.018],[1.793,0]],"v":[[2.914,-0.344],[0,1.5],[-2.914,-0.344],[0,-1.5]],"c":true}]},{"i":{"x":0.333,"y":1},"o":{"x":0.667,"y":0},"t":18,"s":[{"i":[[0,-1.181],[1.407,0],[0,1.181],[-1.407,0]],"o":[[0,1.181],[-1.407,0],[0,-1.181],[1.407,0]],"v":[[2.226,-0.341],[0,1.74],[-2.211,-0.341],[0,-1.74]],"c":true}]},{"i":{"x":0.333,"y":1},"o":{"x":0.667,"y":0},"t":26,"s":[{"i":[[0,-0.905],[1.381,0],[0,0.905],[-1.381,0]],"o":[[0,0.905],[-1.381,0],[0,-0.905],[1.381,0]],"v":[[2.5,-0.306],[0,1.333],[-2.5,-0.306],[0,-1.333]],"c":true}]},{"t":32,"s":[{"i":[[0,-1.018],[1.381,0],[0,1.018],[-1.381,0]],"o":[[0,1.018],[-1.381,0],[0,-1.018],[1.381,0]],"v":[[2.5,-0.344],[0,1.5],[-2.5,-0.344],[0,-1.5]],"c":true}]}],"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"color","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆形","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"body","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,34.204,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-3.866,0],[0,3.866],[3.866,0],[0,-3.866]],"o":[[3.866,0],[0,-3.866],[-3.866,0],[0,3.866]],"v":[[0,4.599],[7,-2.401],[0,-9.401],[-7,-2.401]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.207,0.359],[2.438,0],[1.189,-2.104],[-0.361,-0.204],[-0.204,0.361],[-1.915,0],[-0.932,-1.613],[-0.359,0.207]],"o":[[-1.198,-2.072],[-2.462,0],[-0.204,0.361],[0.361,0.204],[0.925,-1.638],[1.897,0],[0.207,0.359],[0.359,-0.207]],"v":[[5.848,8.225],[0,4.849],[-5.88,8.282],[-5.596,9.304],[-4.574,9.02],[0,6.349],[4.549,8.976],[5.574,9.25]],"c":true},"ix":2},"nm":"路径 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"合并路径 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,0.267,0.639,1,0.5,0.241,0.596,1,1,0.216,0.553,1],"ix":9}},"s":{"a":0,"k":[-3.812,-4.384],"ix":5},"e":{"a":0,"k":[6.345,8.129],"ix":6},"t":1,"nm":"color","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"Union","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"ct":1,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"icon","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,33,0],"ix":2,"l":2},"a":{"a":0,"k":[33,33,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":0,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":8,"s":[70,70,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":18,"s":[110,110,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":26,"s":[90,90,100]},{"t":32,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"w":66,"h":66,"ip":0,"op":60,"st":0,"bm":0}],"markers":[],"props":{}}

View File

@ -34,18 +34,18 @@ try {
var script = document.createElement("script")
document.body.appendChild(script)
if (isDebug) {
script.src = "https://dev-and-static.ghzs66.com/web/js/halo.js" + "?timestamp=" + Math.round(new Date().getTime() / 1000)
script.src = "https://resource.ghzs.com/js/halo_app_test.js" + "?timestamp=" + Math.round(new Date().getTime() / 1000)
} else {
script.src = "https://and-static.ghzs66.com/web/js/halo.js" + "?timestamp=" + Math.round(new Date().getTime() / 1000 / 1000)
script.src = "https://resource.ghzs.com/js/halo.js" + "?timestamp=" + Math.round(new Date().getTime() / 1000 / 1000)
}
var style = document.createElement("link")
style.rel = "stylesheet"
style.type = "text/css"
if (isDebug) {
style.href = "https://dev-and-static.ghzs66.com/web/css/halo.css" + "?timestamp=" + Math.round(new Date().getTime() / 1000)
style.href = "https://resource.ghzs.com/css/halo_app_test.css" + "?timestamp=" + Math.round(new Date().getTime() / 1000)
} else {
style.href = "https://and-static.ghzs66.com/web/css/halo.css" + "?timestamp=" + Math.round(new Date().getTime() / 1000 / 1000)
style.href = "https://resource.ghzs.com/css/halo.css" + "?timestamp=" + Math.round(new Date().getTime() / 1000 / 1000)
}
document.head.appendChild(style)

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -4,7 +4,6 @@ import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.SharedPreferences
import android.os.Message
import android.text.TextUtils
import android.view.View
import android.view.ViewGroup
@ -55,7 +54,7 @@ object AdDelegateHelper {
private var mCsjAdImpl: ICsjAdProvider? = null
private var mBeiziAdImpl: IBeiziAdProvider? = null
private val mAdConfigList: ArrayList<AdConfig> by lazy { arrayListOf() }
private var mAdConfigList: ArrayList<AdConfig>? = null
private var mSplashAd: AdConfig? = null
private var mDownloadManagerAd: AdConfig? = null
@ -107,7 +106,7 @@ object AdDelegateHelper {
@SuppressLint("CheckResult")
fun requestAdConfig(isFromRetry: Boolean, keyword: String = "", callback: (() -> Unit)? = null) {
// mAdConfigList 不为空不需要重试
if (isFromRetry && mAdConfigList.isNotEmpty()) {
if (isFromRetry && mAdConfigList != null) {
return
}
val paramsMap = if (keyword.isNotEmpty()) mapOf("keyword" to keyword) else mapOf()
@ -130,7 +129,7 @@ object AdDelegateHelper {
// 若接口请求失败时,从 SP 里获取上次缓存的数据
val cachedConfig: List<AdConfig>? = SPUtils.getString(mAdConfigSp, KEY_CACHE_CONFIG).toObject()
if (cachedConfig != null && mAdConfigList.isEmpty()) {
if (cachedConfig != null) {
handleAdConfig(cachedConfig)
}
@ -157,13 +156,11 @@ object AdDelegateHelper {
* 处理广告配置
*/
fun handleAdConfig(configList: List<AdConfig>) {
mAdConfigList.clear()
mGameSearchAdList.clear()
mSplashAd = null
mDownloadManagerAd = null
mVGameLaunchAd = null
for (config in configList) {
mAdConfigList.add(config)
// 处理返回的数据
when (config.location) {
"halo_launch" -> {
@ -193,8 +190,7 @@ object AdDelegateHelper {
/**
* 热启动是否需要显示开屏广告
*/
private fun shouldShowStartUpAdWhenHotLaunch() =
mSplashAd?.displayRule?.hotStartSplashAd?.type == AD_TYPE_SDK && mSplashAd?.hotStartThirdPartyAd != null
private fun shouldShowStartUpAdWhenHotLaunch() = mSplashAd?.displayRule?.hotStartSplashAd?.type == AD_TYPE_SDK
/**
* 是否需要显示下载管理广告
@ -361,6 +357,11 @@ object AdDelegateHelper {
isHotLaunch: Boolean,
hideCallback: () -> Unit
) {
val timeout = if (isHotLaunch) {
((mSplashAd!!.displayRule.hotStartSplashAd?.timeout ?: 3.5F) * 1000).toInt()
} else {
(mSplashAd!!.displayRule.timeout * 1000).toInt()
}
// 第三方开屏广告回调,失败时根据接口配置选项决定是否显示自有开屏广告
val sdkSplashCallback: (isSuccess: Boolean) -> Unit = { isSuccess ->
if (isSuccess) {
@ -388,28 +389,20 @@ object AdDelegateHelper {
}
}
val thirdPartyAd = if (isHotLaunch) mSplashAd?.hotStartThirdPartyAd else mSplashAd?.thirdPartyAd
// 第三方广告的数据为空,按加载失败处理
if (mSplashAd == null || thirdPartyAd == null) {
if (mSplashAd?.thirdPartyAd == null) {
sdkSplashCallback.invoke(false)
return
}
val timeout = if (isHotLaunch) {
((mSplashAd?.displayRule?.hotStartSplashAd?.timeout ?: 3.5F) * 1000).toInt()
} else {
((mSplashAd?.displayRule?.timeout ?: 3.5F) * 1000).toInt()
}
if (thirdPartyAd.sourceName == AD_SDK_BEIZI) {
if (mSplashAd?.thirdPartyAd?.sourceName == AD_SDK_BEIZI) {
sdkStartAdContainer.visibility = View.VISIBLE
requestBeiziSplashAd(sdkStartAdContainer, adsViewGroup, adViewWidthInPx, adViewHeightInPx, timeout.toLong(), sdkSplashCallback)
} else if (thirdPartyAd.sourceName == AD_SDK_CSJ) {
} else if (mSplashAd?.thirdPartyAd?.sourceName == AD_SDK_CSJ) {
sdkStartAdContainer.visibility = View.VISIBLE
requestCsjSplashAd(
activity,
thirdPartyAd.slotId,
mSplashAd?.thirdPartyAd?.slotId ?: "unknown",
adViewWidthInPx,
adViewHeightInPx,
adViewWidthInDp,
@ -577,17 +570,6 @@ object AdDelegateHelper {
(if (linkEntity.type != null) linkEntity.type else "")!!,
(if (linkEntity.link != null) linkEntity.link else "")!!
)
SensorsBridge.trackEvent(
"SplashAdOwnSkip",
"splash_ad_id",
ad.id,
"link_type",
linkEntity.type ?: "",
"link_id",
linkEntity.link ?: "",
"link_text",
linkEntity.text ?: ""
)
}
val sources: MutableList<ExposureSource> = ArrayList()
sources.add(ExposureSource("开屏广告", ad.id))
@ -595,19 +577,7 @@ object AdDelegateHelper {
ExposureManager.log(event)
if (ad.button) {
jumpDetailBtn.setOnClickListener { v: View ->
val linkEntity = ad.jump
directToLinkPage(v.context, linkEntity, "(启动广告)", "", event)
SensorsBridge.trackEvent(
"SplashAdOwnClick",
"splash_ad_id",
ad.id,
"link_type",
linkEntity.type ?: "",
"link_id",
linkEntity.link ?: "",
"link_text",
linkEntity.text ?: ""
)
directToLinkPage(v.context, ad.jump, "(启动广告)", "", event)
v.postDelayed({
handler.removeMessages(MainActivity.COUNTDOWN_AD)
hideCallback.invoke()
@ -619,10 +589,7 @@ object AdDelegateHelper {
LogUtils.logStartAd("start_ads", ad)
}
SPUtils.setLong(Constants.SP_LAST_SPLASH_AD_SHOW_TIME, System.currentTimeMillis())
val msg = Message.obtain()
msg.what = MainActivity.COUNTDOWN_AD
msg.obj = ad
handler.sendMessageDelayed(msg, 1000)
handler.sendEmptyMessageDelayed(MainActivity.COUNTDOWN_AD, 1000)
}
/**

View File

@ -44,7 +44,7 @@ import org.json.JSONObject
import java.io.File
// TODO: 移动到module_bbs模块
abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> constructor() : ToolBarActivity(),
abstract class BaseRichEditorActivity<VM : BaseRichEditorViewModel> : ToolBarActivity(),
KeyboardHeightObserver, UploadVideoListener {
lateinit var mRichEditor: RichEditor

View File

@ -12,13 +12,13 @@ import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.fragment.WaitingDialogFragment
import com.gh.gamecenter.common.entity.ErrorEntity
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.runOnUiThread
import com.gh.gamecenter.core.utils.MD5Utils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.common.entity.ErrorEntity
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.entity.ForumDetailEntity
import com.gh.gamecenter.entity.LocalVideoEntity
import com.gh.gamecenter.entity.QuoteCountEntity
@ -28,6 +28,7 @@ import com.gh.gamecenter.retrofit.service.ApiService
import com.gh.gamecenter.video.upload.OnUploadListener
import com.gh.gamecenter.video.upload.UploadManager
import com.google.gson.JsonObject
import com.lightgame.download.FileUtils
import com.lightgame.utils.Utils
import com.zhihu.matisse.Matisse
import com.zhihu.matisse.internal.utils.PathUtils
@ -61,6 +62,7 @@ abstract class BaseRichEditorViewModel(application: Application) : AndroidViewMo
val TITLE_MIN_LENGTH = 6
val MIN_TEXT_LENGTH = 6
val MAX_TEXT_LENGTH = 10000
val FILE_HOST = "file:///"
var id = ""//视频标记
var videoId = ""//更改封面视频id
val quoteCountEntity = QuoteCountEntity()//数据上报用
@ -127,13 +129,15 @@ abstract class BaseRichEditorViewModel(application: Application) : AndroidViewMo
}
val map = LinkedHashMap<String, String>()
for (key in imageUrlMap.keys) {
val localFileUri = FILE_HOST + key.decodeURI()
// 文件格式为 HEIC 时,使用经 OSS 转码的图片作为预览图片
if (FileUtils.getFileMimeType(getApplication(), key.decodeURI())?.lowercase(Locale.CHINA)?.contains("heic") == true) {
val transformedImgUrl = ImageUtils.getIdealImageUrl(imageUrlMap[key], 5000) ?: ""
val transformedImgUrl = ImageUtils.getTransformedUrl(imageUrlMap[key], 5000) ?: ""
map[MD5Utils.getUrlMD5(key)] = transformedImgUrl
mapImages[transformedImgUrl.decodeURI()] = imageUrlMap[key] ?: ""
} else {
map[MD5Utils.getUrlMD5(key)] = imageUrlMap[key] ?: ""
map[MD5Utils.getUrlMD5(key)] = localFileUri
mapImages[TextUtils.htmlEncode(key).decodeURI()] = imageUrlMap[key] ?: ""
}
}

View File

@ -46,7 +46,7 @@ abstract class DownloadToolbarActivity : ToolBarActivity() {
override fun inflateMenu(res: Int) {
super.inflateMenu(res)
if (!getBoolean(Constants.SP_TEENAGER_MODE) && showDownloadMenu()) {
if (showDownloadMenu()) {
createDownloadMenu(res)
}
}
@ -60,7 +60,7 @@ abstract class DownloadToolbarActivity : ToolBarActivity() {
}
val downloadMenuView = mActionMenuView.menu.findItem(R.id.menu_download).actionView
mDownloadCountHint = downloadMenuView?.findViewById(R.id.menu_download_count_hint)
mDownloadCountHint?.typeface = Typeface.createFromAsset(assets, Constants.DIN_FONT_PATH)
mDownloadCountHint?.typeface = Typeface.createFromAsset(assets, "fonts/d_din_bold_only_number.ttf")
}
override fun onMenuItemClick(item: MenuItem?): Boolean {

View File

@ -4,7 +4,6 @@ import android.app.Activity
import android.app.Application
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.alibaba.android.arouter.launcher.ARouter
import com.gh.ad.AdDelegateHelper
import com.gh.common.util.FloatingBackViewManager
import com.gh.common.xapk.XapkInstaller
@ -15,11 +14,11 @@ import com.gh.gamecenter.SplashAdActivity
import com.gh.gamecenter.SplashScreenActivity
import com.gh.gamecenter.authorization.AuthorizationActivity
import com.gh.gamecenter.common.base.GlobalActivityManager
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.utils.PackageFlavorHelper
import com.gh.gamecenter.core.provider.IPushProvider
import com.gh.gamecenter.login.view.LoginActivity
import com.gh.vspace.VHelper
import com.halo.assistant.HaloApp
import com.lg.vspace.ui.launcher.LaunchActivity
// TODO移动到对应的模块
class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
@ -76,6 +75,8 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
}
if (activity is AppCompatActivity
&& activity !is LaunchActivity
&& activity !is LoginActivity
&& activity !is SplashScreenActivity
&& activity !is SkipActivity
&& activity !is AuthorizationActivity
@ -84,10 +85,6 @@ class GlobalActivityLifecycleObserver : Application.ActivityLifecycleCallbacks {
}
XapkInstaller.updateCurrentInstallStatus()
// 清除桌面角标
val pushProvider = ARouter.getInstance().build(RouteConsts.provider.push).navigation() as? IPushProvider
pushProvider?.cleanBadgeNumber(activity.applicationContext)
}
override fun onActivityPaused(activity: Activity) {

View File

@ -45,6 +45,7 @@ import com.gh.gamecenter.login.user.LoginTag
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.login.user.UserRepository
import com.gh.gamecenter.login.utils.LoginHelper
import com.gh.gamecenter.login.utils.QuickLoginHelper
import com.gh.gamecenter.login.view.LoginActivity
import com.gh.gamecenter.personalhome.border.AvatarBorderActivity
import com.gh.gamecenter.setting.SettingBridge
@ -129,12 +130,12 @@ class DefaultJsApi(
@JavascriptInterface
fun login(msg: Any) {
// if (SPUtils.getBoolean(Constants.SP_HAS_GET_PHONE_INFO) || NetworkUtils.isOpenMobileData(context)) {
// QuickLoginHelper.startLogin(context, "浏览器")
// } else {
if (SPUtils.getBoolean(Constants.SP_HAS_GET_PHONE_INFO) || NetworkUtils.isOpenMobileData(context)) {
QuickLoginHelper.startLogin(context, "浏览器")
} else {
val intent = LoginActivity.getIntent(context, "浏览器")
context.startActivity(intent)
// }
}
}
@JavascriptInterface
@ -219,7 +220,7 @@ class DefaultJsApi(
runOnUiThread {
// 若畅玩列表中安装了,优先启动畅玩游戏
if (VHelper.isInstalled(packageName)) {
if (!VHelper.showDialogIfVSpaceIsNeeded(context, "", "", "", "")) {
VHelper.validateVSpaceBeforeAction(context, packageName, null) {
VHelper.launch(context, packageName)
}
} else {
@ -328,11 +329,6 @@ class DefaultJsApi(
return HaloApp.getInstance().gid
}
@JavascriptInterface
fun getOaid(msg: Any): String {
return HaloApp.getInstance().oaid
}
@JavascriptInterface
fun showIncompatibleVersionDialog(msg: Any) {
DialogHelper.showUpgradeDialog(context)

View File

@ -15,6 +15,9 @@ import com.gh.common.util.DirectUtils.directToLegacyVideoDetail
import com.gh.common.util.DirectUtils.directToLinkPage
import com.gh.common.util.DirectUtils.directToQa
import com.gh.common.util.PackageUtils
import com.gh.gamecenter.LibaoDetailActivity
import com.gh.gamecenter.MainActivity
import com.gh.gamecenter.NewsDetailActivity
import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
@ -31,12 +34,12 @@ import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.entity.ActivityLabelEntity
import com.gh.gamecenter.entity.SubjectRecommendEntity
import com.gh.gamecenter.entity.VideoLinkEntity
import com.gh.gamecenter.eventbus.EBSkip
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.utils.PlatformUtils
import com.gh.gamecenter.fragment.MainWrapperFragment
import com.gh.gamecenter.gamecollection.publish.GameCollectionEditActivity
import com.gh.gamecenter.libao.LibaoDetailActivity
import com.gh.gamecenter.newsdetail.NewsDetailActivity
import com.gh.gamecenter.qa.BbsType
import com.gh.gamecenter.qa.video.publish.VideoPublishActivity
import com.gh.gamecenter.subject.SubjectActivity
@ -48,8 +51,8 @@ import java.nio.charset.Charset
object DefaultUrlHandler {
@JvmStatic
fun interceptUrl(context: Context, url: String, entrance: String, sourceEntrance: String = ""): Boolean {
return interceptUrl(context, url, null, entrance, false, sourceEntrance)
fun interceptUrl(context: Context, url: String, entrance: String): Boolean {
return interceptUrl(context, url, null, entrance, false)
}
/**
@ -63,8 +66,7 @@ object DefaultUrlHandler {
fun interceptUrl(context: Context, url: String,
traceEvent: ExposureEvent? = null,
entrance: String,
bringAppToFront: Boolean = false,
sourceEntrance: String = ""): Boolean {
bringAppToFront: Boolean = false): Boolean {
val uri = Uri.parse(url)
if ("ghzhushou" == uri.scheme) {
Utils.log("url = $url")
@ -133,7 +135,7 @@ object DefaultUrlHandler {
}
}
"question" -> DirectUtils.directToQuestionDetail(context, id, entrance, "文章链接", sourceEntrance)
"question" -> DirectUtils.directToQuestionDetail(context, id, entrance, "文章链接")
"real_name" -> DirectUtils.directToRealName(context)
@ -176,7 +178,7 @@ object DefaultUrlHandler {
if ("articles" == type) {
DirectUtils.directToCommunityArticle(
context, typeId, communityId,
entrance, "文章链接", sourceEntrance
entrance, "文章链接"
)
}
}
@ -244,22 +246,24 @@ object DefaultUrlHandler {
act,
paginationType,
fieldId,
sectionName,
sourceEntrance = sourceEntrance
sectionName
)
}
EntranceConsts.HOST_VIDEO_DETAIL -> {
DirectUtils.directToVideoDetail(context, id, entrance, path, sourceEntrance)
DirectUtils.directToVideoDetail(context, id, entrance, path)
}
EntranceConsts.HOST_VIDEO_SINGLE -> {
val referer = uri.getQueryParameter("referer") ?: ""
DirectUtils.directToVideoDetail(
context, id, VideoDetailContainerViewModel.Location.SINGLE_VIDEO.value,
false, "", entrance, "", if (TextUtils.isEmpty(referer)) "" else referer, sourceEntrance
false, "", entrance, "", if (TextUtils.isEmpty(referer)) "" else referer
)
}
EntranceConsts.HOST_VIDEO_STREAMING_HOME -> {
DirectUtils.directToHomeVideoTab(context)
intent = Intent(context, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
intent.putExtra(MainActivity.SWITCH_TO_VIDEO, true)
context.startActivity(intent)
}
EntranceConsts.HOST_VIDEO_STREAMING_DESC -> {
directToGameDetailVideoStreaming(context, id, entrance)
@ -321,7 +325,7 @@ object DefaultUrlHandler {
val linkData = Base64.decode(dataString, Base64.DEFAULT)
val linkDataString = String(linkData, Charset.defaultCharset())
val le = gson.fromJson(linkDataString, LinkEntity::class.java)
directToLinkPage(context, le, entrance, sourceEntrance, "")
directToLinkPage(context, le, entrance, "")
}
} catch (e: Exception) {
e.printStackTrace()
@ -360,8 +364,9 @@ object DefaultUrlHandler {
}
EntranceConsts.HOST_FORUM -> {
val position = uri.getQueryParameter(EntranceConsts.KEY_POSITION)?.toInt()
DirectUtils.directToHomeCommunityTab(context)
DirectUtils.directToForum(context, position ?: 0)
}
EntranceConsts.HOST_UPLOAD_VIDEO_NEW -> {
@ -498,11 +503,13 @@ object DefaultUrlHandler {
EntranceConsts.HOST_GAME_LIBRARY -> {
DirectUtils.directToMainActivity(context)
EventBus.getDefault().post(EBSkip(MainActivity.EB_SKIP_MAIN, MainWrapperFragment.INDEX_GAME))
}
EntranceConsts.HOST_HOME_GAME_COLLECTION_SQUARE -> {
DirectUtils.directToMainActivity(context)
DirectUtils.directToHomeDefaultTab(context)
EventBus.getDefault()
.post(EBSkip(MainActivity.EB_SKIP_MAIN, MainWrapperFragment.INDEX_HOME))
EventBus.getDefault().post(EBReuse(host))
}
@ -557,7 +564,7 @@ object DefaultUrlHandler {
}
// 处理内部页面逻辑
if (transformNormalScheme(context, url, entrance, sourceEntrance)) {
if (transformNormalScheme(context, url, entrance)) {
return true
}
@ -566,14 +573,14 @@ object DefaultUrlHandler {
}
@JvmStatic
fun transformNormalScheme(context: Context, url: String, entrance: String, sourceEntrance: String): Boolean {
val b = transformNewNormalScheme(context, url, entrance, sourceEntrance)
fun transformNormalScheme(context: Context, url: String, entrance: String): Boolean {
val b = transformNewNormalScheme(context, url, entrance)
if (b) return b
return transformOldNormalScheme(context, url, entrance, sourceEntrance)
return transformOldNormalScheme(context, url, entrance)
}
@JvmStatic
fun transformOldNormalScheme(context: Context, url: String, entrance: String, sourceEntrance: String): Boolean {
fun transformOldNormalScheme(context: Context, url: String, entrance: String): Boolean {
val uri = Uri.parse(url)
if (uri.host == "www.ghzs666.com"
|| uri.host == "www.ghzs.com"
@ -589,7 +596,6 @@ object DefaultUrlHandler {
DirectUtils.directToGameDetail(
context,
gameId,
"",
entrance,
autoDownload = false,
traceEvent = null
@ -599,7 +605,7 @@ object DefaultUrlHandler {
val questionId = split("/")[2]
val answerId = uri.getQueryParameter("answer")
if (answerId.isNullOrEmpty()) {
DirectUtils.directToQuestionDetail(context, questionId, entrance, "", sourceEntrance)
DirectUtils.directToQuestionDetail(context, questionId, entrance, "")
} else {
DirectUtils.directToAnswerDetail(context, answerId, entrance, "")
}
@ -629,7 +635,7 @@ object DefaultUrlHandler {
if ("articles" == type || "article" == type) {
DirectUtils.directToCommunityArticle(
context, typeId, communityId,
entrance, "文章链接", sourceEntrance
entrance, "文章链接"
)
}
}
@ -660,7 +666,7 @@ object DefaultUrlHandler {
}
@JvmStatic
fun transformNewNormalScheme(context: Context, url: String, entrance: String, sourceEntrance: String): Boolean {
fun transformNewNormalScheme(context: Context, url: String, entrance: String): Boolean {
val uri = Uri.parse(url)
if (uri.host == "www.ghzs666.com"
|| uri.host == "www.ghzs.com"
@ -678,7 +684,7 @@ object DefaultUrlHandler {
val articleId = splits[2].substring(7)
DirectUtils.directToCommunityArticle(
context, articleId, "",
entrance, "文章链接", sourceEntrance
entrance, "文章链接"
)
}
//https://m.ghzs666.com/article/文章ID
@ -698,7 +704,7 @@ object DefaultUrlHandler {
//https://m.ghzs666.com/bbs/video-视频ID
splits.size >= 3 && splits[1] == "bbs" && splits[2].startsWith("video-") -> {
val videoId = splits[2].substring(6)
DirectUtils.directToVideoDetail(context, videoId, entrance, sourceEntrance)
DirectUtils.directToVideoDetail(context, videoId, entrance)
}
else -> return false
}

View File

@ -2,16 +2,17 @@ package com.gh.common
import com.gh.common.exposure.ExposureManager
import com.gh.common.filter.RegionSettingHelper
import com.gh.common.util.AdHelper
import com.gh.common.videolog.VideoRecordUtils
import com.gh.download.DownloadDataHelper
import com.gh.gamecenter.common.loghub.LoghubUtils
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.doOnMainProcessOnly
import com.gh.gamecenter.common.utils.tryCatchInRelease
import com.gh.gamecenter.core.runOnUiThread
import com.gh.gamecenter.entity.TimeEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import io.reactivex.schedulers.Schedulers
import kotlin.concurrent.fixedRateTimer
@ -25,6 +26,7 @@ object FixedRateJobHelper {
private const val DOWNLOAD_HEARTBEAT_PERIOD: Long = 60 * 1000L
private const val DOWNLOAD_HEARTBEAT_SHEET_PERIOD: Long = 15 * 1000L
private const val STARTUP_AD: Long = 30 * 60 * 1000L
private var mExecuteCount: Int = 0
@ -32,56 +34,58 @@ object FixedRateJobHelper {
@JvmStatic
fun begin() {
// 时间检查每15秒检查一次
fixedRateTimer("Global-Fixed-Rate-Timer", initialDelay = 100, period = CHECKER_PERIOD) {
val elapsedTime = mExecuteCount * CHECKER_PERIOD
// 时间校对10分钟一次
if (elapsedTime % TIME_PERIOD == 0L) {
RetrofitManager.getInstance().api.time
.subscribeOn(Schedulers.io())
.subscribe(object : Response<TimeEntity>() {
override fun onResponse(response: TimeEntity?) {
val serverTime = response?.time
serverTime?.let {
timeDeltaBetweenServerAndClient = it * 1000 - System.currentTimeMillis()
doOnMainProcessOnly {
// 时间检查每15秒检查一次
fixedRateTimer("Global-Fixed-Rate-Timer", initialDelay = 100, period = CHECKER_PERIOD) {
val elapsedTime = mExecuteCount * CHECKER_PERIOD
// 时间校对10分钟一次
if (elapsedTime % TIME_PERIOD == 0L) {
RetrofitManager.getInstance().api.time
.subscribeOn(Schedulers.io())
.subscribe(object : Response<TimeEntity>() {
override fun onResponse(response: TimeEntity?) {
val serverTime = response?.time
serverTime?.let {
timeDeltaBetweenServerAndClient = it * 1000 - System.currentTimeMillis()
}
}
}
})
}
// 提交曝光数据
if (elapsedTime % EXPOSURE_PERIOD == 0L) {
ExposureManager.commitSavedExposureEvents(true)
}
// 分片检测下载进度
if (elapsedTime % DOWNLOAD_HEARTBEAT_SHEET_PERIOD == 0L) {
tryCatchInRelease {
val upload = (mExecuteCount * CHECKER_PERIOD) % DOWNLOAD_HEARTBEAT_PERIOD == 0L
DownloadDataHelper.uploadDownloadHeartbeat(upload)
})
}
}
// 提交普通 loghub 数据
if (elapsedTime % LOGHUB_PERIOD == 0L) {
runOnUiThread {
LoghubUtils.commitSavedLoghubEvents(true)
// 提交曝光数据
if (elapsedTime % EXPOSURE_PERIOD == 0L) {
ExposureManager.commitSavedExposureEvents(true)
}
}
// 更新游戏屏蔽信息
if (elapsedTime % REGION_SETTING_PERIOD == 0L) {
if (HaloApp.getInstance().isRunningForeground) {
RegionSettingHelper.getRegionSetting()
// 分片检测下载进度
if (elapsedTime % DOWNLOAD_HEARTBEAT_SHEET_PERIOD == 0L) {
tryCatchInRelease {
val upload = (mExecuteCount * CHECKER_PERIOD) % DOWNLOAD_HEARTBEAT_PERIOD == 0L
DownloadDataHelper.uploadDownloadHeartbeat(upload)
}
}
}
// 提交视频浏览记录数据
if (elapsedTime % VIDEO_RECORD_PERIOD == 0L) {
VideoRecordUtils.commitVideoRecord()
}
// 提交普通 loghub 数据
if (elapsedTime % LOGHUB_PERIOD == 0L) {
runOnUiThread {
LoghubUtils.commitSavedLoghubEvents(true)
}
}
mExecuteCount++
// 更新游戏屏蔽信息
if (elapsedTime % REGION_SETTING_PERIOD == 0L) {
if (HaloApp.getInstance().isRunningForeground) {
RegionSettingHelper.getRegionSetting()
}
}
// 提交视频浏览记录数据
if (elapsedTime % VIDEO_RECORD_PERIOD == 0L) {
VideoRecordUtils.commitVideoRecord()
}
mExecuteCount++
}
}
}
}

View File

@ -1,351 +0,0 @@
package com.gh.common.browse
import android.os.Handler
import android.os.Looper
import android.os.Message
import androidx.lifecycle.*
import androidx.lifecycle.Lifecycle.Event
/**
* 浏览时长计时器核心接口类,用于页面浏览时长相关埋点上报
*/
interface IBrowseTimerCore {
/**
* 开始计时
*/
fun start()
/**
* 结束计时
*/
fun stop()
}
/**
* 浏览时长计时器核心实现类
*/
class BrowseTimerCore internal constructor() : IBrowseTimerCore {
/**
* 延迟执行的时间
*/
var delayInMills: Long = 3000L
/**
* 开始计时函数回调
*/
var onStart: (() -> Unit)? = null
/**
* 结束计时函数回调
*/
var onResult: ((Long) -> Unit)? = null
/**
* 开始计时的时间点
*/
private var startTimeInMills: Long = 0L
/**
* Handler操作类
*/
private val handler = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
if (msg.what == MESSAGE_START) {
dispatchOnStart()
}
}
}
/**
* 延迟执行开始计时
* @see delayInMills
* @see onStart
*/
override fun start() {
if (delayInMills <= 0) {
dispatchOnStart()
} else {
handler.sendEmptyMessageDelayed(MESSAGE_START, delayInMills)
}
}
/**
* 结束计时,统计浏览时长并回调结束计时函数
* @see onResult
*/
override fun stop() {
handler.removeMessages(MESSAGE_START)
if (startTimeInMills > 0L) {
onResult?.invoke(System.currentTimeMillis() - startTimeInMills)
startTimeInMills = 0L
}
}
/**
* 开始计时,回调开始计时函数
*/
private fun dispatchOnStart() {
startTimeInMills = System.currentTimeMillis()
onStart?.invoke()
}
companion object {
private const val MESSAGE_START = 1
}
}
/**
* 无数据浏览计时器接口类
*/
interface IBrowseTimer : IBrowseTimerCore {
fun withDelayInMills(delayInMills: Long): IBrowseTimer
fun withStart(onStart: () -> Unit): IBrowseTimer
fun withResult(onResult: (Long) -> Unit): IBrowseTimer
}
/**
* 无数据的浏览计时器实现类
*/
class BrowseTimer : IBrowseTimer {
private val core = BrowseTimerCore()
private var isStarted: Boolean = false
override fun withDelayInMills(delayInMills: Long): IBrowseTimer {
core.delayInMills = delayInMills
return this
}
override fun withStart(onStart: () -> Unit): IBrowseTimer {
core.onStart = onStart
return this
}
override fun withResult(onResult: (Long) -> Unit): IBrowseTimer {
core.onResult = onResult
return this
}
override fun start() {
if (isStarted) return
isStarted = true
core.start()
}
override fun stop() {
if (!isStarted) return
core.stop()
isStarted = false
}
}
/**
* 支持Lifecycle的无数据的浏览计时器
*/
class LifecycleBoundBrowseTimer internal constructor(
private val base: IBrowseTimer,
private val onStateChanged: (IBrowseTimer, Event) -> Unit
) : IBrowseTimer, LifecycleEventObserver {
override fun withDelayInMills(delayInMills: Long): IBrowseTimer {
return base.withDelayInMills(delayInMills)
}
override fun withStart(onStart: () -> Unit): IBrowseTimer {
return base.withStart(onStart)
}
override fun withResult(onResult: (Long) -> Unit): IBrowseTimer {
return base.withResult(onResult)
}
override fun start() {
base.start()
}
override fun stop() {
base.stop()
}
override fun onStateChanged(source: LifecycleOwner, event: Event) {
onStateChanged.invoke(this, event)
}
}
fun IBrowseTimer.withLifecycle(
owner: LifecycleOwner,
onStateChanged: (IBrowseTimer, Event) -> Unit = { timer, event ->
when(event) {
Event.ON_START -> timer.start()
Event.ON_STOP -> timer.stop()
else -> {}
}
}
): LifecycleBoundBrowseTimer = LifecycleBoundBrowseTimer(this, onStateChanged).apply {
owner.lifecycle.addObserver(this)
}
/**
* 带数据的浏览计时器接口类
*/
interface IValueBrowseTimer<T> : IBrowseTimerCore {
fun withDelayInMills(delayInMills: Long): IValueBrowseTimer<T>
fun withStart(onStart: (T?) -> Unit): IValueBrowseTimer<T>
fun withResult(onResult: (T?, Long) -> Unit): IValueBrowseTimer<T>
fun dispatchValue(value: T?)
}
/**
* 带数据的浏览计时器实现类
*/
class ValueBrowseTimer<T> : IValueBrowseTimer<T> {
private val core = BrowseTimerCore()
private var isDispatchValue: Boolean = false
private var isStarted: Boolean = false
private var value: T? = null
override fun withDelayInMills(delayInMills: Long): IValueBrowseTimer<T> {
core.delayInMills = delayInMills
return this
}
override fun withStart(onStart: (T?) -> Unit): IValueBrowseTimer<T> {
core.onStart = { onStart.invoke(value) }
return this
}
override fun withResult(onResult: (T?, Long) -> Unit): IValueBrowseTimer<T> {
core.onResult = { onResult.invoke(value, it) }
return this
}
override fun start() {
if (isStarted) return
isStarted = true
if (isDispatchValue) {
core.start()
}
}
override fun stop() {
if (!isStarted) return
core.stop()
isStarted = false
}
override fun dispatchValue(value: T?) {
this.value = value
if (isStarted && !isDispatchValue) {
core.start()
}
isDispatchValue = true
}
}
/**
* 支持LiveData的带数据的浏览计时器
*/
class ObserverBoundValueBrowseTimer<T> internal constructor(private val base: IValueBrowseTimer<T>) : IValueBrowseTimer<T>, Observer<T> {
override fun withDelayInMills(delayInMills: Long): IValueBrowseTimer<T> {
return base.withDelayInMills(delayInMills)
}
override fun withResult(onResult: (T?, Long) -> Unit): IValueBrowseTimer<T> {
return base.withResult(onResult)
}
override fun withStart(onStart: (T?) -> Unit): IValueBrowseTimer<T> {
return base.withStart(onStart)
}
override fun start() {
base.start()
}
override fun stop() {
base.stop()
}
override fun dispatchValue(value: T?) {
base.dispatchValue(value)
}
override fun onChanged(t: T) {
dispatchValue(t)
}
}
/**
* 支持Lifecycle的带数据的浏览计时器
*/
class LifecycleBoundValueBrowseTimer<T> internal constructor(
private val base: IValueBrowseTimer<T>,
private val onStateChanged: (IValueBrowseTimer<T>, Event) -> Unit
) : IValueBrowseTimer<T>, LifecycleEventObserver {
override fun withDelayInMills(delayInMills: Long): IValueBrowseTimer<T> {
return base.withDelayInMills(delayInMills)
}
override fun withResult(onResult: (T?, Long) -> Unit): IValueBrowseTimer<T> {
return base.withResult(onResult)
}
override fun withStart(onStart: (T?) -> Unit): IValueBrowseTimer<T> {
return base.withStart(onStart)
}
override fun start() {
base.start()
}
override fun stop() {
base.stop()
}
override fun dispatchValue(value: T?) {
base.dispatchValue(value)
}
override fun onStateChanged(source: LifecycleOwner, event: Event) {
onStateChanged.invoke(this, event)
}
}
fun <T> IValueBrowseTimer<T>.asObserver(): ObserverBoundValueBrowseTimer<T> = ObserverBoundValueBrowseTimer(this)
fun <T> IValueBrowseTimer<T>.withLifecycle(
owner: LifecycleOwner,
onStateChanged: (IValueBrowseTimer<T>, Event) -> Unit = { timer, event ->
when(event) {
Event.ON_START -> timer.start()
Event.ON_STOP -> timer.stop()
else -> {}
}
}
): LifecycleBoundValueBrowseTimer<T> = LifecycleBoundValueBrowseTimer(this, onStateChanged).apply {
owner.lifecycle.addObserver(this)
}

View File

@ -0,0 +1,18 @@
package com.gh.common.chain
import android.content.Context
import com.gh.common.dialog.CertificationDialog
import com.gh.gamecenter.feature.entity.GameEntity
class CertificationHandler : DownloadChainHandler() {
override fun handleRequest(context: Context, gameEntity: GameEntity, asVGame: Boolean) {
CertificationDialog.showCertificationDialog(context, gameEntity) {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(asVGame, null)
}
}
}
}

View File

@ -18,15 +18,7 @@ class LandPageAddressHandler : DownloadChainHandler() {
}
DialogUtils.showLandPageAddressDialog(context, gameEntity) {// 跳转第三方落地页
if (gameEntity.isLandPageAddressDialogShowOnly()) {
if (hasNext()) {
getNext()?.handleRequest(context, gameEntity, asVGame)
} else {
processEndCallback?.invoke(asVGame, null)
}
} else {
DirectUtils.directToExternalBrowser(context, gameEntity.landPageAddressDialog!!.link!!)
}
DirectUtils.directToExternalBrowser(context, gameEntity.landPageAddressDialog!!.link!!)
}
}
} else {

View File

@ -16,7 +16,7 @@ class ValidateVSpaceHandler : DownloadChainHandler() {
}
if (asVGame) {
VHelper.validateVSpaceBeforeAction(context, gameEntity) {
VHelper.validateVSpaceBeforeAction(context,gameEntity.getUniquePackageName(), gameEntity) {
closure.invoke()
}
} else {

View File

@ -21,26 +21,36 @@ import com.gh.gamecenter.common.utils.EnvHelper;
import com.gh.gamecenter.core.utils.GsonUtils;
import com.gh.gamecenter.core.utils.SPUtils;
import com.gh.gamecenter.core.utils.UrlFilterUtils;
import com.gh.gamecenter.entity.AppEntity;
import com.gh.gamecenter.entity.GameGuidePopupEntity;
import com.gh.gamecenter.entity.NewApiSettingsEntity;
import com.gh.gamecenter.entity.NewSettingsEntity;
import com.gh.gamecenter.entity.VNewSetting;
import com.gh.gamecenter.entity.VSetting;
import com.gh.gamecenter.feature.entity.NewsEntity;
import com.gh.gamecenter.feature.entity.SettingsEntity;
import com.gh.gamecenter.feature.entity.SimulatorEntity;
import com.gh.gamecenter.feature.utils.ContentBlockedHelper;
import com.gh.gamecenter.retrofit.RetrofitManager;
import com.gh.gamecenter.retrofit.service.VApiService;
import com.gh.vspace.VHelper;
import com.halo.assistant.HaloApp;
import com.lightgame.utils.Utils;
import org.greenrobot.eventbus.EventBus;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import io.reactivex.Single;
import io.reactivex.SingleSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.BehaviorSubject;
import okhttp3.ResponseBody;
public class Config {
@ -57,7 +67,8 @@ public class Config {
public static final String WEIBO_APPKEY = BuildConfig.WEIBO_APPKEY;
public static final String QUICK_LOGIN_APPID = BuildConfig.QUICK_LOGIN_APPID;
public static final String QUICK_LOGIN_APPKEY = BuildConfig.QUICK_LOGIN_APPKEY;
public static final String URL_ARTICLE = "www.ghzs666.com/article/"; // ghzs/ghzs666 统一
// http://www.ghzs666.com/article/${articleId}.html
public static final String URL_ARTICLE = "http://www.ghzs666.com/article/"; // ghzs/ghzs666 统一
private static final String SETTINGS_KEY = "settingsKey";
@ -68,13 +79,58 @@ public class Config {
private static NewApiSettingsEntity.NightMode mNightModeSetting;
private static SimulatorEntity mNewSimulatorEntity;
private static VSetting mVSetting;
private static VNewSetting mVNewSetting;
private static AppEntity mNew32UpdateEntity;
public static BehaviorSubject<VNewSetting> vNewSettingSubject = BehaviorSubject.create();
private static GameGuidePopupEntity mGameGuidePopupEntity;
private static SharedPreferences mDefaultSharedPreferences;
public static final String FIX_DOWNLOAD_KEY = "isFixDownload";
public static final String FIX_PLUGIN_KEY = "isFixPlugin";
public static final int VIDEO_PAGE_SIZE = 21; // 视频列表大多都是一行3个
public static boolean isShow() {
return !SPUtils.getBoolean(Constants.SP_TEENAGER_MODE);
if (SPUtils.getBoolean(Constants.SP_TEENAGER_MODE)) return false;
if (getPreferences().getBoolean(FIX_DOWNLOAD_KEY, false)) return true;
if (!isExistDownloadFilter()) return false;
for (SettingsEntity.Download entity : getSettings().getDownload()) {
if ("all".equals(entity.getGame())) {
if (entity.getPluginfy() && "normal".equals(entity.getPolicy()) && filterTime(entity.getTime())) {
return true;
}
}
}
return false;
}
public static boolean isShowDownload(String gameId) {
if (getPreferences().getBoolean(FIX_DOWNLOAD_KEY, false)) return true;
if (TextUtils.isEmpty(gameId) || !isExistDownloadFilter())
return false;
for (SettingsEntity.Download entity : getSettings().getDownload()) {
if (gameId.equals(entity.getGame())) {
if ("normal".equals(entity.getPolicy()) && filterTime(entity.getTime())) {
return true;
} else {
return false;
}
} else if ("all".equals(entity.getGame())) {
if ("normal".equals(entity.getPolicy()) && filterTime(entity.getTime())) {
return true;
}
}
}
return false;
}
/**
@ -90,11 +146,76 @@ public class Config {
return mNewApiSettingsEntity.getInstall().getVpnRequired().getShouldShowVpnOption();
}
public static boolean isShowPlugin(String gameId) {
SharedPreferences preferences = getPreferences();
boolean isFixPlugin = preferences.getBoolean(FIX_PLUGIN_KEY, false);
if (isFixPlugin) return true;
if (TextUtils.isEmpty(gameId) || !isExistDownloadFilter())
return false;
for (SettingsEntity.Download entity : getSettings().getDownload()) {
if (gameId.equals(entity.getGame())) {
if (entity.getPluginfy() && filterTime(entity.getTime())) {
return true;
} else {
return false;
}
}
if ("all".equals(entity.getGame())) {
if (entity.getPluginfy() && filterTime(entity.getTime())) {
preferences.edit().putBoolean(FIX_PLUGIN_KEY, true).apply();
return true;
}
}
}
return false;
}
public static boolean isShowPlugin() {
SharedPreferences preferences = getPreferences();
boolean isFixPlugin = preferences.getBoolean(FIX_PLUGIN_KEY, false);
if (isFixPlugin) return true;
if (!isExistDownloadFilter())
return false;
for (SettingsEntity.Download entity : getSettings().getDownload()) {
if ("all".equals(entity.getGame())) {
if (entity.getPluginfy() && filterTime(entity.getTime())) {
preferences.edit().putBoolean(FIX_PLUGIN_KEY, true).apply();
return true;
}
}
}
return false;
}
private static boolean filterTime(SettingsEntity.Download.TimeEntity timeEntity) {
long end = timeEntity.getEnd();
long start = timeEntity.getStart();
long curTime = Utils.getTime(HaloApp.getInstance().getApplication());
if ((start == 0 || curTime >= start) && (end == 0 || curTime <= end)) {
return true;
}
return false;
}
public static void setSettings(SettingsEntity settingsEntity) {
getPreferences().edit().putString(SETTINGS_KEY, GsonUtils.toJson(settingsEntity)).apply();
mSettingsEntity = settingsEntity;
PackageHelper.refreshList();
// 更新设置状态
mSettingsEntity.showArticleEntrance();
mSettingsEntity.showCommunityEntrance();
// 加载完设置后刷新下
PackageHelper.initList();
}
@Nullable
@ -195,6 +316,27 @@ public class Config {
return mVSetting;
}
@Nullable
public static VNewSetting getVNewSettingEntity() {
if (mVNewSetting == null) {
try {
String json = SPUtils.getString(Constants.SP_V_NEW_SETTINGS);
if (!TextUtils.isEmpty(json)) {
mVNewSetting = GsonUtils.fromJson(json, VNewSetting.class);
vNewSettingSubject.onNext(mVNewSetting);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return mVNewSetting;
}
@Nullable
public static AppEntity getNew32UpdateEntity() {
return mNew32UpdateEntity;
}
/**
* 请求网络数据,尝试刷新畅玩相关配置
*/
@ -215,11 +357,62 @@ public class Config {
});
}
@SuppressLint("CheckResult")
public static void getNewSetting() {
VApiService vApi = RetrofitManager.getInstance().getVApi();
vApi.getNewSettings(BuildConfig.VERSION_NAME, Build.VERSION.SDK_INT).flatMap(new Function<VNewSetting, SingleSource<AppEntity>>() {
@Override
public SingleSource<AppEntity> apply(VNewSetting data) throws Exception {
mVNewSetting = data;
vNewSettingSubject.onNext(mVNewSetting);
SPUtils.setString(Constants.SP_V_NEW_SETTINGS, GsonUtils.toJson(data));
if (data.getVa() != null && data.getVa().getArch32() != null) {
String versionNameByPackageName = PackageUtils.getVersionNameByPackageName(data.getVa().getArch32().getPackageName());
return vApi.getNewPackageUpdate(
BuildConfig.VERSION_NAME,
versionNameByPackageName != null ? versionNameByPackageName : "",
HaloApp.getInstance().getChannel()
);
}
return Single.error(new IllegalStateException("VNewSetting entity is not expected"));
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new BiResponse<AppEntity>() {
@Override
public void onSuccess(AppEntity data) {
mNew32UpdateEntity = data;
}
});
}
@Nullable
public static GameGuidePopupEntity getGameGuidePopupEntity() {
return mGameGuidePopupEntity;
}
private static boolean isExistDownloadFilter() {
if (getSettings() == null || getSettings().getDownload() == null || getSettings().getDownload().size() == 0) {
return false;
} else {
return true;
}
}
public static void filterPluginArticle(List<NewsEntity> list) {
if (isShowPlugin() || list == null) return;
for (int i = 0; i < list.size(); i++) {
NewsEntity newsEntity = list.get(i);
String title = newsEntity.getTitle();
if (!TextUtils.isEmpty(title) && title.contains("插件")) {
list.remove(i);
i--;
}
}
}
public static SharedPreferences getPreferences() {
if (mDefaultSharedPreferences == null) {
mDefaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().getApplication());
@ -250,6 +443,9 @@ public class Config {
GsonUtils.toJson(response.getSuggestion()));
edit.apply();
if (!getPreferences().getBoolean(Config.FIX_DOWNLOAD_KEY, false) && Config.isShow()) {
getPreferences().edit().putBoolean(Config.FIX_DOWNLOAD_KEY, true).apply();
}
if (!SPUtils.getBoolean(Constants.SP_TEENAGER_MODE)) {
EventBus.getDefault().post(new EBReuse("Refresh"));
}
@ -269,6 +465,7 @@ public class Config {
});
refreshVSettingEntity();
getNewSetting();
RetrofitManager.getInstance()
.getApi().getGameGuidePopup(Build.MANUFACTURER, Build.VERSION.RELEASE, Build.MODEL, channel, BuildConfig.VERSION_NAME)

View File

@ -15,6 +15,7 @@ import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.gh.common.chain.BrowserInstallHandler;
import com.gh.common.chain.CertificationHandler;
import com.gh.common.chain.DownloadChainBuilder;
import com.gh.common.chain.DownloadChainHandler;
import com.gh.common.chain.CheckDownloadHandler;
@ -52,8 +53,6 @@ import com.gh.gamecenter.WebActivity;
import com.gh.gamecenter.common.entity.LinkEntity;
import com.gh.gamecenter.common.utils.DarkModeUtils;
import com.gh.gamecenter.common.utils.ExtensionsKt;
import com.gh.gamecenter.common.utils.FileUtils;
import com.gh.gamecenter.common.utils.ImageUtils;
import com.gh.gamecenter.common.utils.NewFlatLogUtils;
import com.gh.gamecenter.common.utils.SensorsBridge;
import com.gh.gamecenter.core.utils.MtaHelper;
@ -71,14 +70,13 @@ import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment;
import com.gh.gamecenter.manager.PackagesManager;
import com.gh.vspace.VHelper;
import com.lightgame.download.DownloadEntity;
import com.lightgame.download.FileUtils;
import com.lightgame.utils.Utils;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import kotlin.collections.CollectionsKt;
/**
* Created by khy on 12/02/18.
*/
@ -98,29 +96,20 @@ public class BindingAdapters {
}
}
public static void setDownloadButton(DownloadButton progressBar,
GameEntity gameEntity,
ExposureEvent traceEvent,
@Nullable View.OnClickListener clickCallBack,
@Nullable String entrance,
@Nullable String location) {
setDownloadButton(progressBar, gameEntity, traceEvent, clickCallBack, entrance, location, "其他");
}
// 大图下的进度条
public static void setDownloadButton(DownloadButton progressBar,
GameEntity gameEntity,
ExposureEvent traceEvent,
@Nullable View.OnClickListener clickCallBack,
@Nullable String entrance,
@Nullable String location,
String sourceEntrance) {
@Nullable String location) {
// 恢复DialogFragment
restoreDialogFragment(progressBar);
// 判断是否显示按钮
if (gameEntity != null
&& Config.isShowDownload(gameEntity.getId())
&& !"光环助手".equals(gameEntity.getName())) {
progressBar.setVisibility(View.VISIBLE);
} else {
@ -135,7 +124,7 @@ public class BindingAdapters {
case DOWNLOADING_PLUGIN:
case DOWNLOADING_NORMAL:
Intent intent = DownloadManagerActivity.getDownloadMangerIntent(v.getContext(),
gameEntity.getApk().isEmpty() ? "" : gameEntity.getApk().get(0).getUrl(), entrance);
gameEntity.getApk().get(0).getUrl(), entrance);
v.getContext().startActivity(intent);
break;
case NONE:
@ -167,6 +156,7 @@ public class BindingAdapters {
builder.addHandler(new BrowserInstallHandler());
builder.addHandler(new PackageCheckHandler());
builder.addHandler(new DownloadDialogHelperHandler());
builder.addHandler(new CertificationHandler());
builder.addHandler(new VersionNumberHandler());
builder.addHandler(new LandPageAddressHandler());
builder.addHandler(new OverseaDownloadHandler());
@ -195,6 +185,7 @@ public class BindingAdapters {
DownloadChainBuilder builder = new DownloadChainBuilder();
builder.addHandler(new UnsupportedFeatureHandler());
builder.addHandler(new GamePermissionHandler());
builder.addHandler(new CertificationHandler());
builder.addHandler(new VersionNumberHandler());
builder.setProcessEndCallback((asVGame, isSubscribe) -> {
@ -221,7 +212,7 @@ public class BindingAdapters {
if (gameEntity.getApk().size() == 1) {
//启动模拟器游戏
if (SimulatorGameManager.isSimulatorGame(gameEntity)) {
DownloadEntity downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(gameEntity.getApk().isEmpty() ? "" : gameEntity.getApk().get(0).getUrl());
DownloadEntity downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(gameEntity.getApk().get(0).getUrl());
if (downloadEntity != null) {
File file = new File(downloadEntity.getPath());
if (!file.exists()) {
@ -281,7 +272,7 @@ public class BindingAdapters {
case RESERVABLE:
GamePermissionDialogFragment.show((AppCompatActivity) v.getContext(), gameEntity, gameEntity.getInfo(), () -> {
CheckLoginUtils.checkLogin(progressBar.getContext(), "", () -> {
ReservationHelper.reserve(v.getContext(), gameEntity, sourceEntrance, () -> {
ReservationHelper.reserve(v.getContext(), gameEntity.getId(), gameEntity.getName(), () -> {
LogUtils.logReservation(gameEntity, traceEvent);
updateReservation(progressBar, gameEntity);
});
@ -459,9 +450,9 @@ public class BindingAdapters {
ToastUtils.toast(context.getString(R.string.unsupported_browser_install_hint));
}
String buttonText = progressBar.getText();
ApkEntity apkEntity = CollectionsKt.firstOrNull(gameEntity.getApk());
String msg = FileUtils.isCanDownload(progressBar.getContext(), apkEntity == null ? "" : apkEntity.getSize());
if (apkEntity != null && TextUtils.isEmpty(msg)) {
ApkEntity apkEntity = gameEntity.getApk().get(0);
String msg = FileUtils.isCanDownload(progressBar.getContext(), apkEntity.getSize());
if (TextUtils.isEmpty(msg)) {
DownloadManager.createDownload(progressBar.getContext(),
apkEntity,
gameEntity,
@ -549,10 +540,11 @@ public class BindingAdapters {
}
}
public static void setGameName(TextView view, GameEntity game, boolean isShowPlatform) {
public static void setGameName(TextView view, GameEntity game, boolean isShowPlatform, @Nullable Boolean isShowSuffix) {
if (isShowSuffix == null) isShowSuffix = true; // 默认显示
String gameName;
if (isShowPlatform && game.getApk().size() > 0) {
gameName = String.format("%s - %s", game.getName(),
gameName = String.format("%s - %s", !isShowSuffix ? game.getNameWithoutSuffix() : game.getName(),
PlatformUtils.getInstance(view.getContext()).getPlatformName(
game.getApk().get(0).getPlatform()));
if (!gameName.equals((String) view.getTag(R.string.tag_game_name_id))) {
@ -560,7 +552,7 @@ public class BindingAdapters {
view.setTag(R.string.tag_game_name_id, gameName);
}
} else {
gameName = game.getName();
gameName = !isShowSuffix ? game.getNameWithoutSuffix() : game.getName();
if (gameName != null && !gameName.equals((String) view.getTag(R.string.tag_game_name_id))) {
view.setText(gameName);
view.setTag(R.string.tag_game_name_id, gameName);

View File

@ -0,0 +1,221 @@
package com.gh.common.dialog
import android.annotation.SuppressLint
import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.graphics.Paint
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.widget.CheckBox
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.gh.gamecenter.common.avoidcallback.AvoidOnResultManager
import com.gh.gamecenter.common.avoidcallback.Callback
import com.gh.gamecenter.common.constant.Constants
import com.gh.common.util.*
import com.gh.gamecenter.R
import com.gh.gamecenter.ShellActivity
import com.gh.gamecenter.common.callback.ConfirmListener
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.feature.entity.AuthDialogEntity
import com.gh.gamecenter.feature.entity.AuthDialogLevel
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.login.user.UserManager
import com.google.gson.reflect.TypeToken
import com.halo.assistant.fragment.user.UserInfoEditFragment
import com.lightgame.utils.AppManager
class CertificationDialog(
context: Context,
private val authDialogEntity: AuthDialogEntity,
val gameEntity: GameEntity,
val listener: ConfirmListener
) :
Dialog(context, R.style.GhAlertDialog) {
private lateinit var view: View
private lateinit var detailedDesTv: TextView
private lateinit var noRemindAgainCb: CheckBox
private lateinit var actionLeftTv: TextView
private lateinit var actionRightTv: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
view = LayoutInflater.from(context).inflate(R.layout.dialog_sertification, null)
setContentView(view)
detailedDesTv = view.findViewById(R.id.detailedDesTv)
noRemindAgainCb = view.findViewById(R.id.noRemindAgainCb)
actionLeftTv = view.findViewById(R.id.actionLeftTv)
actionRightTv = view.findViewById(R.id.actionRightTv)
detailedDesTv.paint.flags = Paint.UNDERLINE_TEXT_FLAG
detailedDesTv.paint.isAntiAlias = true
detailedDesTv.setOnClickListener {
DirectUtils.directToWebView(context, authDialogEntity.link)
}
when (authDialogEntity.level) {
AuthDialogLevel.MUST_PASS.value -> {
actionLeftTv.text = "暂不下载"
actionRightTv.text = "去实名认证"
noRemindAgainCb.visibility = View.GONE
actionLeftTv.setOnClickListener {
SensorsBridge.trackEvent("VerificationPopupClick", "button_name", actionLeftTv.text.toString())
dismiss()
}
actionRightTv.setOnClickListener {
SensorsBridge.trackEvent("VerificationPopupClick", "button_name", actionRightTv.text.toString())
if (UserManager.getInstance().isLoggedIn) {
gotoAuthPage()
} else {
gotoLoginPage()
}
}
}
AuthDialogLevel.ALWAYS_HINT.value -> {
actionLeftTv.text = "去实名认证"
actionRightTv.text = "继续下载"
noRemindAgainCb.visibility = View.GONE
actionLeftTv.setOnClickListener {
SensorsBridge.trackEvent("VerificationPopupClick", "button_name", actionLeftTv.text.toString())
if (UserManager.getInstance().isLoggedIn) {
gotoAuthPage()
} else {
gotoLoginPage()
}
}
actionRightTv.setOnClickListener {
SensorsBridge.trackEvent("VerificationPopupClick", "button_name", actionRightTv.text.toString())
listener.onConfirm()
dismiss()
}
}
AuthDialogLevel.OPTIONAL_HINT.value -> {
actionLeftTv.text = "去实名认证"
actionRightTv.text = "继续下载"
noRemindAgainCb.visibility = View.VISIBLE
actionLeftTv.setOnClickListener {
SensorsBridge.trackEvent("VerificationPopupClick", "button_name", actionLeftTv.text.toString())
if (noRemindAgainCb.isChecked) {
SPUtils.setBoolean(gameEntity.id, true)
}
if (UserManager.getInstance().isLoggedIn) {
gotoAuthPage()
} else {
gotoLoginPage()
}
}
actionRightTv.setOnClickListener {
SensorsBridge.trackEvent("VerificationPopupClick", "button_name", actionRightTv.text.toString())
if (noRemindAgainCb.isChecked) {
SPUtils.getBoolean(gameEntity.id, true)
}
listener.onConfirm()
dismiss()
}
}
}
SensorsBridge.trackEvent(
"VerificationDialogShow",
"game_id",
gameEntity.id,
"game_name",
gameEntity.name ?: "",
"game_type",
gameEntity.categoryChinese
)
}
//跳转登录页面
private fun gotoLoginPage() {
val currentActivity = AppManager.getInstance().currentActivity() ?: return
CheckLoginUtils.checkLogin(
currentActivity as AppCompatActivity,
null, true, "实名认证弹窗"
) {
if (UserManager.getInstance().isAuth) {
listener.onConfirm()
dismiss()
}
}
}
//跳转实名认证页面
private fun gotoAuthPage() {
val currentActivity = AppManager.getInstance().currentActivity() ?: return
AvoidOnResultManager.getInstance(currentActivity as AppCompatActivity)
.startForResult(
ShellActivity.getIntent(
context,
ShellActivity.Type.REAL_NAME_INFO,
).apply {
putExtra(EntranceConsts.KEY_GAME_ID, gameEntity.id)
}, object : Callback {
override fun onActivityResult(resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK && data != null) {
val isAuthSuccess =
data.getBooleanExtra(UserInfoEditFragment.AUTH_SUCCESS, false)
if (isAuthSuccess) {
listener.onConfirm()
dismiss()
}
}
}
})
}
companion object {
@JvmStatic
fun showCertificationDialog(context: Context, game: GameEntity, listener: ConfirmListener) {
//1.先判断是否登录 是执行2 否执行3
//2.判断是否实名认证 是终止 否执行3
//3.判断是否需要弹出认证弹窗接口
if (UserManager.getInstance().isLoggedIn) {
if (UserManager.getInstance().isAuth) {//已实名认证
listener.onConfirm()
} else {
authDialog(context, game, listener)
}
} else {
authDialog(context, game, listener)
}
}
@SuppressLint("CheckResult")
private fun authDialog(context: Context, game: GameEntity, listener: ConfirmListener) {
var authDialog: AuthDialogEntity? = null
if (game.authDialog != null) {
authDialog = game.authDialog
}
if (authDialog == null) {
val datas = SPUtils.getString(Constants.SP_AUTH_DIALOG)
val type = object : TypeToken<List<AuthDialogEntity>>() {}.type
val authDialogs = GsonUtils.gson.fromJson<List<AuthDialogEntity>>(datas, type)
if (!authDialogs.isNullOrEmpty()) {
authDialog = authDialogs.find { it.gameCategory == game.category }
}
}
val isCloseAuthDialog = SPUtils.getBoolean(game.id, false)
if (authDialog != null && (authDialog.level != AuthDialogLevel.OPTIONAL_HINT.value || !isCloseAuthDialog)) {
val dialog = CertificationDialog(context, authDialog, game, listener)
dialog.show()
} else {
listener.onConfirm()
}
}
}
}

View File

@ -23,7 +23,6 @@ class GameOffServiceDialogFragment : BaseDialogFragment() {
private var mDialog: GameEntity.Dialog? = null
private var mBinding: DialogGameOffServiceBinding? = null
private var mCallback: (() -> Unit)? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -45,7 +44,6 @@ class GameOffServiceDialogFragment : BaseDialogFragment() {
titleTv.text = title
contentTv.text = HtmlCompat.fromHtml(content, HtmlCompat.FROM_HTML_MODE_LEGACY)
okTv.setOnClickListener {
mCallback?.invoke()
dismissAllowingStateLoss()
}
@ -66,6 +64,7 @@ class GameOffServiceDialogFragment : BaseDialogFragment() {
siteTv.text = site.text
siteTv.paintFlags = siteTv.paintFlags or Paint.UNDERLINE_TEXT_FLAG
siteTv.setOnClickListener {
// MtaHelper.onEvent("游戏下载状态按钮", getKey(), site.text)
DirectUtils.directToWebView(requireContext(), site.url, "(关闭下载弹窗)")
dismissAllowingStateLoss()
}
@ -84,13 +83,11 @@ class GameOffServiceDialogFragment : BaseDialogFragment() {
const val KEY_DIALOG = "dialog"
@JvmStatic
fun getInstance(dialog: GameEntity.Dialog, callback: (() -> Unit)? = null) =
GameOffServiceDialogFragment().apply {
arguments = Bundle().apply {
putParcelable(KEY_DIALOG, dialog)
}
mCallback = callback
fun getInstance(dialog: GameEntity.Dialog) = GameOffServiceDialogFragment().apply {
arguments = Bundle().apply {
putParcelable(KEY_DIALOG, dialog)
}
}
}
}

View File

@ -1,68 +0,0 @@
package com.gh.common.dialog
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.provider.Settings
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import com.gh.gamecenter.common.databinding.DialogAlertDefaultBinding
import com.lightgame.dialog.BaseDialogFragment
@RequiresApi(Build.VERSION_CODES.R)
class ManagerAllFilesPermissionDialogFragment : BaseDialogFragment() {
private val mBinding by lazy { DialogAlertDefaultBinding.inflate(layoutInflater) }
private var mCallBack: (() -> Unit)? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return mBinding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mBinding.run {
titleTv.text = "请求权限"
titleTv.gravity = Gravity.CENTER
contentTv.text = "需要所有文件访问权限,请打开权限设置页面"
confirmTv.setOnClickListener {
val intent = Intent().apply {
action = Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION
data = Uri.fromParts("package", requireContext().packageName, null)
}
requireActivity().startActivityForResult(intent, REQUEST_CODE)
}
cancelTv.setOnClickListener {
dismissAllowingStateLoss()
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE && Environment.isExternalStorageManager()) {
mCallBack?.invoke()
dismissAllowingStateLoss()
}
}
companion object {
const val REQUEST_CODE = 1000
@JvmStatic
fun show(activity: AppCompatActivity, callback: () -> Unit) {
ManagerAllFilesPermissionDialogFragment().apply {
mCallBack = callback
}.show(
activity.supportFragmentManager,
ManagerAllFilesPermissionDialogFragment::class.java.name
)
}
}
}

View File

@ -19,7 +19,6 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.util.DirectUtils
import com.gh.common.util.LogUtils
import com.gh.common.util.PackageHelper
import com.gh.common.util.PackageUtils
import com.gh.download.DownloadManager
import com.gh.gamecenter.R
@ -60,7 +59,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
private val mDuration = 3000
private var mDisposable: Disposable? = null
private var mAdapter: PackageCheckAdapter? = null
private var mAllInstalledPackages = PackageHelper.getInstalledPackages(HaloApp.getInstance().application, 0)
private var mAllInstalledPackages = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0)
var gameEntity: GameEntity? = null
var callBack: ConfirmListener? = null
@ -326,7 +325,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
override fun onResume() {
super.onResume()
mAllInstalledPackages = PackageHelper.getInstalledPackages(HaloApp.getInstance().application, 0)
mAllInstalledPackages = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0)
gameEntity?.packageDialog?.let {
if (isAllPackageInstalled(mAllInstalledPackages, it)) {
callBack?.onConfirm()
@ -364,7 +363,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMainThread(busFour: EBPackage) {
if (busFour.isInstalledOrUninstalled()) {
mAllInstalledPackages = PackageHelper.getInstalledPackages(HaloApp.getInstance().application, 0)
mAllInstalledPackages = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0)
mAdapter?.notifyDataSetChanged()
}
}
@ -417,7 +416,7 @@ class PackageCheckDialogFragment : BaseDialogFragment() {
return
}
val allInstalledPackages = PackageHelper.getInstalledPackages(HaloApp.getInstance().application, 0)
val allInstalledPackages = PackageUtils.getInstalledPackages(HaloApp.getInstance().application, 0)
if (isAllPackageInstalled(allInstalledPackages, packageDialogEntity)) {
callBack.onConfirm()
return

View File

@ -29,15 +29,6 @@ class PrivacyPolicyDialogFragment : BaseDialogFragment() {
private var mCallBack: ((isSuccess: Boolean) -> Unit)? = null
private val mBinding by lazy { DialogPrivacyProtocolBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState != null) {
dismiss()
return
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,

View File

@ -24,15 +24,6 @@ class ReserveDialog : BaseDialogFragment() {
private lateinit var mReserveList: List<SimpleGameEntity>
private var mDismissListener: (() -> Unit)? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState != null) {
dismiss()
return
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val binding: DialogReserveBinding = DialogReserveBinding.inflate(layoutInflater, null, false)

View File

@ -27,7 +27,7 @@ object ExposureUtils {
): ExposureEvent {
val gameEntity = entity.copy()
gameEntity.id = if (entity.id.contains(DownloadEntity.GAME_ID_DIVIDER)) {
entity.id.split(DownloadEntity.GAME_ID_DIVIDER).toTypedArray().firstOrNull() ?: ""
entity.id.split(DownloadEntity.GAME_ID_DIVIDER).toTypedArray()[0]
} else {
entity.id
}

View File

@ -19,7 +19,7 @@ import com.halo.assistant.HaloApp
@Database(
entities = [AnswerEntity::class, ArticleEntity::class, NewsEntity::class, HistoryGameEntity::class, MyVideoEntity::class, GamesCollectionEntity::class],
version = 14,
version = 13,
exportSchema = false
)
@TypeConverters(
@ -41,8 +41,7 @@ import com.halo.assistant.HaloApp
SimpleGameListConverter::class,
TagInfoListConverter::class,
ActivityLabelListConverter::class,
IconFloatConverter::class,
SectionConverter::class
IconFloatConverter::class
)
abstract class HistoryDatabase : RoomDatabase() {
@ -144,14 +143,6 @@ abstract class HistoryDatabase : RoomDatabase() {
}
}
val MIGRATION_13_14: Migration = object : Migration(13, 14) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("Alter TABLE ArticleEntity add type TEXT NOT NULL DEFAULT 'community_article'")
database.execSQL("Alter TABLE ArticleEntity add sections TEXT NOT NULL DEFAULT ''")
database.execSQL("Alter TABLE ArticleEntity add tagActivityName TEXT NOT NULL DEFAULT ''")
}
}
val instance by lazy {
Room.databaseBuilder(
HaloApp.getInstance().application,
@ -169,7 +160,6 @@ abstract class HistoryDatabase : RoomDatabase() {
.addMigrations(MIGRATION_10_11)
.addMigrations(MIGRATION_11_12)
.addMigrations(MIGRATION_12_13)
.addMigrations(MIGRATION_13_14)
.build()
}
}

View File

@ -6,7 +6,11 @@ import com.gh.gamecenter.common.utils.removeVideoContent
import com.gh.gamecenter.common.utils.tryCatchInRelease
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.entity.*
import com.gh.gamecenter.feature.entity.*
import com.gh.gamecenter.feature.entity.AnswerEntity
import com.gh.gamecenter.feature.entity.ArticleEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.NewsEntity
import com.gh.gamecenter.feature.entity.User
import com.gh.gamecenter.qa.entity.AnswerDetailEntity
import com.gh.gamecenter.qa.entity.ArticleDetailEntity
@ -71,6 +75,7 @@ object HistoryHelper {
historyGame.iconFloat = gameEntity.iconFloat
historyGame.name = gameEntity.name
historyGame.tagStyle = gameEntity.tagStyle
historyGame.tag = gameEntity.getTag()
historyGame.subtitle = gameEntity.subtitle
historyGame.subtitleStyle = gameEntity.subtitleStyle
return historyGame
@ -104,7 +109,7 @@ object HistoryHelper {
fun deleteArticleEntity(articleId: String) {
runOnIoThread {
tryCatchInRelease {
HistoryDatabase.instance.articleDao().deleteArticle(ArticleEntity(_id = articleId))
HistoryDatabase.instance.articleDao().deleteArticle(ArticleEntity(id = articleId))
}
}
}
@ -165,9 +170,6 @@ object HistoryHelper {
articleEntity.images = articleDetailEntity.images
articleEntity.imagesInfo = articleDetailEntity.imagesInfo
articleEntity.videos = articleDetailEntity.videos
articleEntity.tagActivityName = articleDetailEntity.tagActivityName
articleEntity.sections = articleDetailEntity.sections ?: emptyList()
articleEntity.type = "community_article"
return articleEntity
}

View File

@ -1,10 +0,0 @@
package com.gh.common.iinterface
import com.gh.gamecenter.entity.MultiTabNav
interface IMultiTab {
fun provideMultiTabId(): String
fun provideMultiTabName(): String
fun provideCurrentTabEntity(): MultiTabNav.LinkMultiTabNav?
fun provideLastSelectedPosition(): Int
}

View File

@ -1,10 +0,0 @@
package com.gh.common.iinterface
import com.gh.gamecenter.entity.BottomTab
interface ISearchToolbarTab {
fun onScrollChanged(totalHeight: Int, offset: Int, isDarkModeChanged: Boolean)
fun changeAppBarColor(color: Int, pageId: String)
fun setSearchStyle(searchStyle: BottomTab.SearchStyle)
fun getCurrentTabIndex(): Int?
}

View File

@ -1,12 +0,0 @@
package com.gh.common.iinterface
import com.gh.common.prioritychain.PullDownPushHandler
import com.gh.gamecenter.entity.PullDownPush
interface ISmartRefresh {
fun setSmartRefreshEnabled(isEnable: Boolean)
fun finishTwoLevel(action: String)
fun finishRefresh()
fun popupPullDownPush(finishCallback: () -> Unit)
fun setPullDownPush(pullDownPush: PullDownPush?, pullDownPushHandler: PullDownPushHandler?)
}

View File

@ -1,17 +0,0 @@
package com.gh.common.iinterface
interface ISmartRefreshContent {
/**
* 启用/关闭 页面滑动
* @param isScrollEnabled 是否启用
*/
fun setScrollEnabled(isScrollEnabled: Boolean)
fun onRefresh()
/**
* 启用/关闭 SwipeRefreshLayout 的下拉刷新
* @param isSwipeRefreshEnabled 是否启用
*/
fun setSwipeRefreshEnabled(isSwipeRefreshEnabled: Boolean)
}

View File

@ -1,9 +0,0 @@
package com.gh.common.iinterface
import com.gh.common.prioritychain.PriorityChain
interface ISuperiorChain {
fun registerInferiorChain(chain: PriorityChain)
fun unregisterInferiorChain(chain: PriorityChain)
}

View File

@ -14,7 +14,7 @@ import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.databinding.PopupAccelerateNotificationBinding
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.wrapper.MainWrapperViewModel
import com.gh.gamecenter.fragment.MainWrapperViewModel
class AccelerateNotificationHandler(priority: Int) : PriorityChainHandler(priority) {
@ -42,7 +42,7 @@ class AccelerateNotificationHandler(priority: Int) : PriorityChainHandler(priori
processNext()
} else {
updateStatus(STATUS_VALID)
process()
onProcess()
}
} else {
if (gameEntityList == null) {
@ -53,7 +53,7 @@ class AccelerateNotificationHandler(priority: Int) : PriorityChainHandler(priori
}
}
override fun onProcess() : Boolean {
override fun onProcess() {
when (getStatus()) {
STATUS_VALID -> {
val accelerateSet =
@ -64,7 +64,6 @@ class AccelerateNotificationHandler(priority: Int) : PriorityChainHandler(priori
}
accelerateSet.add(mGameList!![0].messageId)
SPUtils.setStringSet(Constants.SP_ACCELERATE_NOTIFICATION_POP_UP_SET, accelerateSet)
return true
} else {
processNext()
}
@ -74,8 +73,6 @@ class AccelerateNotificationHandler(priority: Int) : PriorityChainHandler(priori
processNext()
}
}
return false
}
companion object {

View File

@ -1,82 +0,0 @@
package com.gh.common.prioritychain
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.gh.gamecenter.floatingwindow.FloatingWindowEntity
import com.gh.gamecenter.livedata.Event
class CustomFloatingWindowHandler(priority: Int) : PriorityChainHandler(priority) {
private val data = arrayListOf<FloatingWindowEntity>()
private val _showFloatingAction = MutableLiveData<Event<ArrayList<FloatingWindowEntity>>>()
val showFloatingAction: LiveData<Event<ArrayList<FloatingWindowEntity>>> = _showFloatingAction
fun setData(newData: List<FloatingWindowEntity>) {
data.clear()
data.addAll(newData)
doPreProcess()
}
private fun doPreProcess() {
// debugOnly {
// data.clear()
// data.add(
// FloatingWindowEntity(
// id = "audire",
// image = "https://jira.shanqu.cc/secure/attachment/57822/57822_image-2023-12-01-17-53-04-492.png",
// link = WelcomeDialogEntity(
// id = null,
// time = null,
// packages = null,
// floatingWindowId = null,
// shouldShowExitAnimation = false
// ),
// pushType = "maiorum",
// expandable = false,
// expandedImage = "fermentum",
// bigPopupNotice = "dignissim"
// )
// )
// }
if (getStatus() == STATUS_PENDING) {
if (data.isNotEmpty()) {
updateStatus(STATUS_VALID)
process()
} else {
processNext()
}
} else {
if (data.isNotEmpty()) {
updateStatus(STATUS_VALID)
} else {
updateStatus(STATUS_INVALID)
}
}
}
override fun onProcess(): Boolean {
when (getStatus()) {
STATUS_VALID -> {
_showFloatingAction.value = Event(data)
processNext()
// floatingWindowProvider.showFloatingWindowOnly(
// mFragment!!,
// mRecyclerView!!,
// mWindowList!!,
// ) {
// val welcomeDialog = WelcomeDialogFragment.getInstance(it, true, mFragment)
// welcomeDialog.show(mFragment!!.childFragmentManager, "WelcomeDialog")
// }
}
STATUS_INVALID -> {
processNext()
}
}
return false
}
}

View File

@ -0,0 +1,87 @@
package com.gh.common.prioritychain
import androidx.recyclerview.widget.RecyclerView
import com.alibaba.android.arouter.launcher.ARouter
import com.gh.gamecenter.common.base.fragment.BaseLazyFragment
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.core.provider.IFloatingWindowProvider
import com.gh.gamecenter.feature.entity.WelcomeDialogEntity
import com.gh.gamecenter.floatingwindow.FloatingWindowEntity
import com.gh.gamecenter.fragment.WelcomeDialogFragment
import com.lightgame.utils.Utils
class FloatingWindowHandler(priority: Int) : PriorityChainHandler(priority) {
private var mFragment: BaseLazyFragment? = null
private var mRecyclerView: RecyclerView? = null
private var mWindowList: ArrayList<FloatingWindowEntity>? = null
fun setData(windowList: ArrayList<FloatingWindowEntity>?) {
mWindowList = windowList
if (mFragment != null) {
doPreProcess()
}
}
fun setView(
fragment: BaseLazyFragment,
recyclerView: RecyclerView
) {
mFragment = fragment
mRecyclerView = recyclerView
if (mWindowList != null) {
doPreProcess()
}
}
private fun doPreProcess() {
Utils.log(TAG, "FloatingWindowHandler preProcess windowSize is -> ${mWindowList?.size}")
if (getStatus() == STATUS_PENDING) {
if (!mWindowList.isNullOrEmpty()) {
updateStatus(STATUS_VALID)
onProcess()
} else {
processNext()
}
} else {
if (!mWindowList.isNullOrEmpty()) {
updateStatus(STATUS_VALID)
} else {
updateStatus(STATUS_INVALID)
}
}
}
override fun onProcess() {
when (getStatus()) {
STATUS_VALID -> {
val floatingWindowProvider =
ARouter.getInstance().build(RouteConsts.provider.floatingwindow)
.navigation() as? IFloatingWindowProvider<WelcomeDialogEntity>
// 强校验所有条件均通过才能显示
if (floatingWindowProvider == null || mFragment == null || mFragment?.isAdded == false || mRecyclerView == null) {
processNext()
return
}
floatingWindowProvider.showFloatingWindowOnly(
mFragment!!,
mRecyclerView!!,
mWindowList!!,
) {
val welcomeDialog = WelcomeDialogFragment.getInstance(it, true, mFragment)
welcomeDialog.show(mFragment!!.childFragmentManager, "WelcomeDialog")
}
}
STATUS_INVALID -> {
processNext()
}
}
}
}

View File

@ -1,244 +0,0 @@
package com.gh.common.prioritychain
import android.annotation.SuppressLint
import android.app.Activity
import android.app.Application.ActivityLifecycleCallbacks
import android.os.Bundle
import android.preference.PreferenceManager
import androidx.fragment.app.FragmentActivity
import com.gh.common.iinterface.ISuperiorChain
import com.gh.common.util.CheckLoginUtils
import com.gh.common.util.PackageUtils
import com.gh.gamecenter.SplashScreenActivity
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.entity.SimpleGameEntity
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.entity.DialogEntity
import com.gh.gamecenter.feature.entity.WelcomeDialogEntity
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
/**
* 全局的 APP 优先级弹窗链管理器
*
* 弹窗的优先级为
* 启动跳转(-101) > 更新弹窗(-100) > 隐私政策弹窗(-99) > 消息通知权限弹窗(0) > 预约弹窗(1) > 启动弹窗(2)
*/
object GlobalPriorityChainHelper : ISuperiorChain {
private val api = RetrofitManager.getInstance().api
private var inferiorChain: PriorityChain? = null
private val mainChain: PriorityChain by lazy { PriorityChain { inferiorChain?.start() } }
/**
* 当前 activity 是否使用于应用全局弹窗的弹出
* 排除启动页和其它非 FragmentActivity
*/
fun isThisActivityValid(activity: Activity?): Boolean {
return activity is FragmentActivity
&& !activity.isFinishing
&& activity !is SplashScreenActivity
}
/**
* 预启动所有的优先级弹窗管理链
*/
fun preStart() {
val launchRedirectHandler = LaunchRedirectHandler(-101)
val updateDialogHandler = UpdateDialogHandler(-100)
val privacyPolicyDialogHandler = PrivacyPolicyDialogHandler(-99)
val notificationPermissionDialogHandler = NotificationPermissionDialogHandler(0)
val reserveDialogHandler = ReserveDialogHandler(1)
val welcomeDialogHandler = WelcomeDialogHandler(2)
mainChain.addHandler(launchRedirectHandler)
mainChain.addHandler(updateDialogHandler)
mainChain.addHandler(privacyPolicyDialogHandler)
mainChain.addHandler(welcomeDialogHandler)
mainChain.addHandler(reserveDialogHandler)
mainChain.addHandler(notificationPermissionDialogHandler)
launchRedirectHandler.doPreProcess()
updateDialogHandler.doPreProcess()
requestOpeningDialogData(welcomeDialogHandler, privacyPolicyDialogHandler)
requestReserveDialogData(reserveDialogHandler)
}
/**
* 启动优先级弹窗管理链的执行
*/
fun start() {
if (mainChain.isHandlerQueueEmpty()) return
mainChain.start()
observeLifecycle()
}
private fun observeLifecycle() {
HaloApp.getInstance().registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
// do nothing
}
override fun onActivityStarted(activity: Activity) {
// do nothing
}
override fun onActivityResumed(activity: Activity) {
// 优先级弹窗管理链为空时取消注册,避免无用调用
if (mainChain.isHandlerQueueEmpty()) {
HaloApp.getInstance().unregisterActivityLifecycleCallbacks(this)
} else {
resume()
}
}
override fun onActivityPaused(activity: Activity) {
// do nothing
}
override fun onActivityStopped(activity: Activity) {
// do nothing
}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
// do nothing
}
override fun onActivityDestroyed(activity: Activity) {
// do nothing
}
})
}
/**
* 恢复链的处理
*/
fun resume() {
mainChain.resume()
}
/**
* 请求首页启动弹窗相关的数据并执行相关 handler 的 preProcess
*/
@SuppressLint("CheckResult")
private fun requestOpeningDialogData(
welcomeDialogHandler: WelcomeDialogHandler,
privacyPolicyDialogHandler: PrivacyPolicyDialogHandler
) {
val sp = PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance())
val lastId = SPUtils.getString(sp, Constants.SP_LAST_OPENING_ID, "")
val lastTime = SPUtils.getLong(sp, Constants.SP_LAST_OPENING_TIME, 0)
val openType = if (HaloApp.getInstance().isNewForThisVersion) "first" else "not_first_time"
api.getOpeningDialog(HaloApp.getInstance().channel, lastId, lastTime, openType)
.subscribeOn(Schedulers.io())
.subscribe(object : BiResponse<DialogEntity>() {
override fun onSuccess(data: DialogEntity) {
var welcomeDialogEntity: WelcomeDialogEntity? = null
var privacyPolicyDialogEntity: DialogEntity.PrivacyPolicyEntity? = null
// 全新安装忽略隐私弹窗
if (data.privacyPolicyDialog != null) {
val id = data.privacyPolicyDialog.id
val lastAcceptedId = SPUtils.getString(Constants.SP_LAST_ACCEPTED_PRIVACY_DIALOG_ID, "")
if (HaloApp.getInstance().isBrandNewInstall) {
SPUtils.setString(Constants.SP_LAST_ACCEPTED_PRIVACY_DIALOG_ID, id)
} else {
if (id != lastAcceptedId) {
privacyPolicyDialogEntity = data.privacyPolicyDialog
}
}
}
// debugOnly {
// privacyPolicyDialogEntity = DialogEntity.PrivacyPolicyEntity(
// "5f6f5f3d9d9b4e0001c3b3a5",
// "privacy_policy",
// "ONCE",
// "INFORM",
// "隐私政策",
// 1601116800000)
// }
privacyPolicyDialogHandler.doPreProcess(privacyPolicyDialogEntity)
// 类型为游戏时判断是否本地已安装该游戏,已安装不弹弹窗
if (data.welcomeDialog != null) {
welcomeDialogEntity = data.welcomeDialog
if (data.welcomeDialog.type == "game") {
if (data.welcomeDialog.packages != null) {
for (packageName in data.welcomeDialog.packages!!) {
if (PackageUtils.isInstalled(HaloApp.getInstance(), packageName)) {
welcomeDialogEntity = null
break
}
}
}
}
}
welcomeDialogHandler.doPreProcess(welcomeDialogEntity)
}
override fun onFailure(exception: Exception) {
privacyPolicyDialogHandler.doPreProcess(null)
welcomeDialogHandler.doPreProcess(null)
}
})
}
/**
* 请求预约弹窗相关的数据
*/
@SuppressLint("CheckResult")
private fun requestReserveDialogData(reserveDialogHandler: ReserveDialogHandler) {
// debugOnly {
// reserveDialogHandler.doPreProcess(arrayListOf(SimpleGameEntity(
// "5f6f5f3d9d9b4e0001c3b3a5",
// "5f6f5f3d9d9b4e0001c3b3a5",
// "https://and-static.ghzs.com/image/game/icon/2022/11/18/63772b0d398daaa7c5067298.png",
// "5f6f5f3d9d9b4e0001c3b3a5",
// )))
// return
// }
if (CheckLoginUtils.isLogin()) {
api.getReserveDialog(UserManager.getInstance().userId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : BiResponse<List<SimpleGameEntity>>() {
override fun onSuccess(data: List<SimpleGameEntity>) {
reserveDialogHandler.doPreProcess(data)
}
override fun onFailure(exception: Exception) {
reserveDialogHandler.doPreProcess(null)
}
})
} else {
reserveDialogHandler.doPreProcess(null)
}
}
override fun registerInferiorChain(chain: PriorityChain) {
inferiorChain = chain
if (mainChain.isHandlerQueueEmpty()) {
inferiorChain?.resume()
}
}
override fun unregisterInferiorChain(chain: PriorityChain) {
if (inferiorChain == chain) {
inferiorChain = null
}
}
}

View File

@ -0,0 +1,45 @@
package com.gh.common.prioritychain
import com.gh.gamecenter.fragment.HomeSearchToolWrapperFragment
class HomePushHandler(priority: Int): PriorityChainHandler(priority) {
private var mHomeFragment: HomeSearchToolWrapperFragment? = null
/**
* 提前预处理显示弹窗的内容
*/
fun doPreProcess(homeFragment: HomeSearchToolWrapperFragment?, shouldShow: Boolean) {
mHomeFragment = homeFragment
if (getStatus() == STATUS_PENDING) {
if (shouldShow && homeFragment != null) {
updateStatus(STATUS_VALID)
onProcess()
} else {
processNext()
}
} else {
if (shouldShow && homeFragment != null) {
updateStatus(STATUS_VALID)
} else {
updateStatus(STATUS_INVALID)
}
}
}
override fun onProcess() {
when (getStatus()) {
STATUS_VALID -> {
// 目前首页下拉二楼是首页最后一个弹窗类的东西,还没实现回调,如果有其它要在它后面弹出的,需要自行在它的实现结果后添加回调
mHomeFragment?.popUpHomePushIfNeeded {
processNext()
}
}
STATUS_INVALID -> {
processNext()
}
}
}
}

View File

@ -1,86 +0,0 @@
package com.gh.common.prioritychain
import android.annotation.SuppressLint
import com.gh.common.util.DirectUtils
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.common.entity.LaunchRedirect
import com.gh.gamecenter.common.entity.LaunchRedirectWrapper
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.wrapper.MainWrapperRepository
import com.halo.assistant.HaloApp
/**
* 初次启动跳转
*/
class LaunchRedirectHandler(priority: Int) : PriorityChainHandler(priority) {
private var launchData: LaunchRedirect? = null
@SuppressLint("CheckResult")
fun doPreProcess() {
// if (true) {
if (HaloApp.getInstance().isBrandNewInstall) {
RetrofitManager.getInstance().newApi
.getLaunchRedirect(BuildConfig.VERSION_NAME, HaloApp.getInstance().channel)
.compose(singleToMain())
.subscribe(object : BiResponse<LaunchRedirectWrapper>() {
override fun onSuccess(data: LaunchRedirectWrapper) {
launchData = data.launchRedirect
if (launchData == null) {
updateStatus(STATUS_INVALID)
processNext()
return
}
// 尝试提前设置 tab default 避免首页数据加载完成tab 选中会闪烁
if (launchData?.type == "bottom_tab") {
MainWrapperRepository.getInstance().sendSelectTabEvent(launchData!!)
}
if (getStatus() == STATUS_PENDING) {
updateStatus(STATUS_VALID)
process()
} else {
updateStatus(STATUS_VALID)
}
}
override fun onFailure(exception: Exception) {
super.onFailure(exception)
updateStatus(STATUS_INVALID)
processNext()
}
})
} else {
updateStatus(STATUS_INVALID)
processNext()
}
}
override fun onProcess(): Boolean {
val currentActivity = CurrentActivityHolder.getCurrentActivity()
if (GlobalPriorityChainHelper.isThisActivityValid(currentActivity)) {
if (getStatus() == STATUS_VALID) {
// 当 type 为 "bottom_tab" 时上面 doPreProcess 中已经处理过了,但再选中一次好像也没有什么问题,先不特殊处理这个 case 了
DirectUtils.directToLinkPage(currentActivity!!, launchData!!, "首次启动跳转", "")
// 跳转页面不管回调,延迟 500ms 后执行下一个 handler
AppExecutor.uiExecutor.executeWithDelay({
processNext()
}, 500L)
return true
} else if (getStatus() == STATUS_INVALID) {
processNext()
}
}
return false
}
}

View File

@ -6,18 +6,15 @@ import com.gh.gamecenter.login.user.UserManager
class NotificationPermissionDialogHandler(priority: Int) : PriorityChainHandler(priority) {
override fun onProcess(): Boolean {
override fun onProcess() {
// 仅登录后再启动光环时请求一次权限
if (UserManager.getInstance().isLoggedIn) {
NotificationHelper.showNotificationHintDialog(NotificationUgc.LOGIN) {
processNext()
}
return true
} else {
processNext()
}
return false
}
}

View File

@ -1,54 +1,22 @@
package com.gh.common.prioritychain
import com.lightgame.utils.Utils
import java.util.*
import java.util.concurrent.PriorityBlockingQueue
class PriorityChain(private val completeCallback: (() -> Unit)? = null) {
class PriorityChain {
private val handlerQueue: Queue<PriorityChainHandler> = PriorityBlockingQueue()
private val mHandlerQueue: Queue<PriorityChainHandler> = PriorityBlockingQueue()
/**
* 添加 handler 到队列中
*/
fun addHandler(handler: PriorityChainHandler) {
handlerQueue.add(handler.also {
mHandlerQueue.add(handler.also {
it.setPriorityChain(this)
})
}
/**
* 启动队列中的 handler
*/
fun start() {
handlerQueue.peek()?.let {
it.injectQueue(handlerQueue)
it.process()
}
mHandlerQueue.poll()?.process(mHandlerQueue)
}
/**
* 恢复队列中的 handler
*/
fun resume() {
val handler = handlerQueue.peek()
if (handler?.getStatus() == PriorityChainHandler.STATUS_HANDLING) {
Utils.log(PriorityChainHandler.TAG, "${handler.javaClass.simpleName} 处于执行中状态,不用恢复")
} else {
handler?.injectQueue(handlerQueue)
handler?.process()
}
}
/**
* 队列是否为空
*/
fun isHandlerQueueEmpty() = handlerQueue.isEmpty()
fun onHandleComplete() {
completeCallback?.invoke()
}
fun isHandlerQueueEmpty() = mHandlerQueue.isEmpty()
}

View File

@ -5,76 +5,54 @@ import java.util.*
abstract class PriorityChainHandler(private val mPriority: Int) : Comparable<PriorityChainHandler> {
private var status = STATUS_UNKNOWN
private var queue: Queue<PriorityChainHandler>? = null
private var mStatus = STATUS_UNKNOWN
private var mQueue: Queue<PriorityChainHandler>? = null
private var priorityChain: PriorityChain? = null
private var mPriorityChain: PriorityChain? = null
/**
* 获取当前 handler 的状态
* - 等待结果返回 STATUS_PENDING
* - 无需执行 STATUS_INVALID
* - 可执行 STATUS_VALID
* - 执行中 STATUS_HANDLING
* - 未知 STATUS_UNKNOWN
*/
fun getStatus(): Int = status
fun getStatus(): Int = mStatus
fun updateStatus(status: Int) {
Utils.log(TAG, "${javaClass.simpleName} updateStatus ${this.status} $status")
Utils.log(TAG, "${javaClass.simpleName} updateStatus $status")
this.status = status
mStatus = status
}
fun setPriorityChain(priorityChain: PriorityChain) {
this.priorityChain = priorityChain
mPriorityChain = priorityChain
}
fun injectQueue(queue: Queue<PriorityChainHandler>) {
this.queue = queue
}
fun process() {
Utils.log(TAG, "${javaClass.simpleName} process $status")
fun process(queue: Queue<PriorityChainHandler>) {
Utils.log(TAG, "${javaClass.simpleName} process $mStatus")
mQueue = queue
// 若当前 handler 未经处理,将其状态改为 pending
if (status == STATUS_UNKNOWN) {
if (mStatus == STATUS_UNKNOWN) {
updateStatus(STATUS_PENDING)
}
if (status == STATUS_HANDLING) {
Utils.log(TAG, "${javaClass.simpleName} 已经处于执行中状态,不用再次执行")
return
}
val isHandling = onProcess()
if (isHandling) {
updateStatus(STATUS_HANDLING)
}
onProcess()
}
/**
* 执行相关功能的地方
* @return 是否满足执行条件并处于执行中状态
*/
abstract fun onProcess(): Boolean
abstract fun onProcess()
/**
* 分发给下一个 handler 处理
*/
fun processNext() {
Utils.log(TAG, "${javaClass.simpleName} processNext")
Utils.log(TAG, "${javaClass.simpleName} processNext $mStatus")
queue?.remove(this)
if (queue?.isEmpty() == true) {
priorityChain?.onHandleComplete()
} else {
queue?.peek()?.let {
it.injectQueue(queue!!)
it.process()
}
}
mQueue?.poll()?.process(mQueue!!)
}
override fun compareTo(other: PriorityChainHandler): Int {
@ -86,7 +64,6 @@ abstract class PriorityChainHandler(private val mPriority: Int) : Comparable<Pri
internal const val STATUS_INVALID = 1
internal const val STATUS_VALID = 2
internal const val STATUS_UNKNOWN = 3
internal const val STATUS_HANDLING = 4
const val TAG = "PriorityChainHandler"
}

View File

@ -2,17 +2,18 @@ package com.gh.common.prioritychain
import androidx.fragment.app.FragmentActivity
import com.gh.common.dialog.PrivacyPolicyDialogFragment
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.entity.DialogEntity
class PrivacyPolicyDialogHandler(priority: Int) : PriorityChainHandler(priority) {
private var mActivity: FragmentActivity? = null
private var mPrivacyPolicyEntity: DialogEntity.PrivacyPolicyEntity? = null
/**
* 提前预处理显示弹窗的内容
*/
fun doPreProcess(privacyPolicyEntity: DialogEntity.PrivacyPolicyEntity?) {
fun doPreProcess(fragmentActivity: FragmentActivity, privacyPolicyEntity: DialogEntity.PrivacyPolicyEntity?) {
mActivity = fragmentActivity
mPrivacyPolicyEntity = privacyPolicyEntity
if (getStatus() == STATUS_PENDING) {
@ -20,7 +21,7 @@ class PrivacyPolicyDialogHandler(priority: Int) : PriorityChainHandler(priority)
processNext()
} else {
updateStatus(STATUS_VALID)
process()
onProcess()
}
} else {
if (privacyPolicyEntity == null) {
@ -31,26 +32,17 @@ class PrivacyPolicyDialogHandler(priority: Int) : PriorityChainHandler(priority)
}
}
override fun onProcess(): Boolean {
val currentActivity = CurrentActivityHolder.getCurrentActivity()
if (GlobalPriorityChainHelper.isThisActivityValid(currentActivity)) {
when (getStatus()) {
STATUS_VALID -> {
PrivacyPolicyDialogFragment.show(currentActivity as FragmentActivity, mPrivacyPolicyEntity) { _: Boolean? ->
processNext()
}
return true
}
STATUS_INVALID -> {
override fun onProcess() {
when(getStatus()) {
STATUS_VALID -> {
PrivacyPolicyDialogFragment.show(mActivity!!, mPrivacyPolicyEntity) { _: Boolean? ->
processNext()
}
}
STATUS_INVALID -> {
processNext()
}
}
return false
}
}

View File

@ -1,48 +0,0 @@
package com.gh.common.prioritychain
import com.gh.common.iinterface.ISmartRefresh
class PullDownPushHandler(priority: Int): PriorityChainHandler(priority) {
private var mSmartRefreshFragment: ISmartRefresh? = null
/**
* 提前预处理显示弹窗的内容
*/
fun doPreProcess(smartRefreshFragment: ISmartRefresh?, shouldShow: Boolean) {
mSmartRefreshFragment = smartRefreshFragment
if (getStatus() == STATUS_PENDING) {
if (shouldShow && smartRefreshFragment != null) {
updateStatus(STATUS_VALID)
process()
} else {
processNext()
}
} else {
if (shouldShow && smartRefreshFragment != null) {
updateStatus(STATUS_VALID)
} else {
updateStatus(STATUS_INVALID)
}
}
}
override fun onProcess(): Boolean {
when (getStatus()) {
STATUS_VALID -> {
mSmartRefreshFragment?.popupPullDownPush {
processNext()
}
return true
}
STATUS_INVALID -> {
processNext()
}
}
return false
}
}

View File

@ -1,18 +1,20 @@
package com.gh.common.prioritychain
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.Fragment
import com.gh.common.dialog.ReserveDialog
import com.gh.gamecenter.common.entity.SimpleGameEntity
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.message.MessageUnreadRepository
class ReserveDialogHandler(priority: Int) : PriorityChainHandler(priority) {
private var mFragment: Fragment? = null
private var mReserveData: List<SimpleGameEntity>? = null
/**
* 提前预处理显示弹窗的内容
*/
fun doPreProcess(reserveData: List<SimpleGameEntity>?) {
fun doPreProcess(fragment: Fragment, reserveData: List<SimpleGameEntity>?) {
mFragment = fragment
mReserveData = reserveData
if (getStatus() == STATUS_PENDING) {
@ -20,7 +22,7 @@ class ReserveDialogHandler(priority: Int) : PriorityChainHandler(priority) {
processNext()
} else {
updateStatus(STATUS_VALID)
process()
onProcess()
}
} else {
if (reserveData.isNullOrEmpty()) {
@ -31,28 +33,21 @@ class ReserveDialogHandler(priority: Int) : PriorityChainHandler(priority) {
}
}
override fun onProcess(): Boolean {
val currentActivity = CurrentActivityHolder.getCurrentActivity()
if (GlobalPriorityChainHelper.isThisActivityValid(currentActivity)) {
when (getStatus()) {
STATUS_VALID -> {
val reserveDialog = ReserveDialog.getInstance(mReserveData!!)
reserveDialog.setOnDismissListener {
processNext()
}
reserveDialog.show((currentActivity as FragmentActivity).supportFragmentManager, "reserveDialog")
return true
}
STATUS_INVALID -> {
override fun onProcess() {
when (getStatus()) {
STATUS_VALID -> {
val reserveDialog = ReserveDialog.getInstance(mReserveData!!)
reserveDialog.setOnDismissListener {
MessageUnreadRepository.loadMessageUnreadData()
processNext()
}
reserveDialog.show(mFragment!!.childFragmentManager, "reserveDialog")
}
STATUS_INVALID -> {
processNext()
}
}
return false
}
}

View File

@ -1,47 +1,17 @@
package com.gh.common.prioritychain
import androidx.fragment.app.FragmentActivity
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.update.UpdateHelper
import android.content.Context
import com.gh.gamecenter.manager.UpdateManager
class UpdateDialogHandler(priority: Int) : PriorityChainHandler(priority) {
class UpdateDialogHandler(context: Context, priority: Int) : PriorityChainHandler(priority) {
fun doPreProcess() {
UpdateHelper.getUpdate(false) {
if (getStatus() == STATUS_PENDING) {
if (UpdateHelper.isUpdateValid(false)) {
updateStatus(STATUS_VALID)
process()
} else {
updateStatus(STATUS_INVALID)
processNext()
}
} else {
if (UpdateHelper.isUpdateValid(false)) {
updateStatus(STATUS_VALID)
} else {
updateStatus(STATUS_INVALID)
}
}
private val mUpdateManager = UpdateManager.getInstance(context)
override fun onProcess() {
mUpdateManager.checkUpdate(true, null)
mUpdateManager.setDismissCallback {
processNext()
}
}
override fun onProcess(): Boolean {
val currentActivity = CurrentActivityHolder.getCurrentActivity()
if (GlobalPriorityChainHelper.isThisActivityValid(currentActivity)) {
if (getStatus() == STATUS_VALID) {
UpdateHelper.showUpdateDialog(currentActivity as FragmentActivity) {
processNext()
}
return true
} else if (getStatus() == STATUS_INVALID) {
processNext()
}
}
return false
}
}

View File

@ -1,37 +1,41 @@
package com.gh.common.prioritychain
import androidx.fragment.app.FragmentActivity
import android.graphics.Bitmap
import androidx.fragment.app.Fragment
import com.gh.gamecenter.common.callback.BiCallback
import com.gh.gamecenter.common.utils.ImageUtils
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.gamecenter.feature.entity.WelcomeDialogEntity
import com.gh.gamecenter.fragment.MainWrapperViewModel
import com.gh.gamecenter.fragment.WelcomeDialogFragment
import com.gh.gamecenter.wrapper.MainWrapperViewModel
import com.halo.assistant.HaloApp
class WelcomeDialogHandler(priority: Int) : PriorityChainHandler(priority) {
class WelcomeDialogHandler(priority: Int): PriorityChainHandler(priority) {
private var welcomeDialogEntity: WelcomeDialogEntity? = null
private var mFragment: Fragment? = null
private var mWelcomeDialogEntity: WelcomeDialogEntity? = null
fun doPreProcess(welcomeDialogEntity: WelcomeDialogEntity?) {
this.welcomeDialogEntity = welcomeDialogEntity
fun doPreProcess(fragment: Fragment, welcomeDialogEntity: WelcomeDialogEntity?) {
mFragment = fragment
mWelcomeDialogEntity = welcomeDialogEntity
val preLoadClosure = {
// 判断启动本次应用是否已经弹窗,不是的话弹启动弹窗
if (HaloApp.get(MainWrapperViewModel.SHOULD_SHOW_OPENING_DIALOG, false) == null) {
HaloApp.put(MainWrapperViewModel.SHOULD_SHOW_OPENING_DIALOG, false)
val idealUrl = ImageUtils.getIdealImageUrl(this.welcomeDialogEntity!!.icon, 0, true) ?: ""
ImageUtils.prefetchToDiskCache(idealUrl) { isSuccess ->
if (isSuccess) {
ImageUtils.getBitmap(mWelcomeDialogEntity!!.icon, object : BiCallback<Bitmap, Boolean> {
override fun onFirst(first: Bitmap) {
if (getStatus() == STATUS_PENDING) {
updateStatus(STATUS_VALID)
process()
onProcess()
} else {
updateStatus(STATUS_VALID)
}
} else {
}
override fun onSecond(second: Boolean) {
processNext()
}
}
})
} else {
processNext()
}
@ -52,28 +56,24 @@ class WelcomeDialogHandler(priority: Int) : PriorityChainHandler(priority) {
}
}
override fun onProcess(): Boolean {
val currentActivity = CurrentActivityHolder.getCurrentActivity()
if (GlobalPriorityChainHelper.isThisActivityValid(currentActivity)) {
when (getStatus()) {
STATUS_VALID -> {
val welcomeDialog = WelcomeDialogFragment.getInstance(welcomeDialogEntity)
override fun onProcess() {
when (getStatus()) {
STATUS_VALID -> {
if (mFragment == null || !mFragment!!.isAdded) {
updateStatus(STATUS_INVALID)
processNext()
} else {
val welcomeDialog = WelcomeDialogFragment.getInstance(mWelcomeDialogEntity)
welcomeDialog.setOnDismissListener {
processNext()
}
welcomeDialog.show((currentActivity as FragmentActivity).supportFragmentManager, "WelcomeDialog")
return true
}
STATUS_INVALID -> {
processNext()
welcomeDialog.show(mFragment!!.childFragmentManager, "WelcomeDialog")
}
}
STATUS_INVALID -> {
processNext()
}
}
return false
}
}

View File

@ -8,6 +8,7 @@ import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.core.provider.IAppProvider
import com.gh.gamecenter.core.provider.IFlavorProvider
import com.halo.assistant.HaloApp
import com.va.host.HostUtils
@Route(path = RouteConsts.provider.app, name = "Application暴露服务")
class AppProviderImpl : IAppProvider {
@ -86,4 +87,6 @@ class AppProviderImpl : IAppProvider {
override fun setSkippingThirdParty(isSkippingThirdParty: Boolean) {
HaloApp.getInstance().isSkippingThirdParty = isSkippingThirdParty
}
override fun getPluginVersion(): String = HostUtils.getPluginVersion()
}

View File

@ -16,8 +16,9 @@ class BindingAdaptersProviderImpl : IBindingAdaptersProvider {
view: TextView,
game: GameEntity,
isShowPlatform: Boolean,
isShowSuffix: Boolean
) {
BindingAdapters.setGameName(view, game, isShowPlatform)
BindingAdapters.setGameName(view, game, isShowPlatform, isShowSuffix)
}
override fun setGameTags(layout: LinearLayout, gameEntity: GameEntity) {

View File

@ -100,6 +100,10 @@ class ConfigProviderImpl : IConfigProvider {
return Config.getNightModeSetting()?.setting ?: false
}
override fun isShowPlugin(gameId: String): Boolean {
return Config.isShowPlugin(gameId)
}
override fun init(context: Context?) {
// Do nothing
}

View File

@ -13,10 +13,9 @@ class DefaultUrlHandlerProviderImpl : IDefaultUrlHandlerProvider {
context: Context,
url: String,
entrance: String,
bringAppToFront: Boolean,
sourceEntrance: String
bringAppToFront: Boolean
): Boolean {
return DefaultUrlHandler.interceptUrl(context, url, null, entrance, bringAppToFront, sourceEntrance)
return DefaultUrlHandler.interceptUrl(context, url, null, entrance, bringAppToFront)
}
override fun init(context: Context?) {

View File

@ -22,6 +22,34 @@ class DirectProviderImpl : IDirectProvider {
DirectUtils.directToQqConversation(context, qq)
}
override fun directToCommodityDetail(context: Context, commodityId: String) {
DirectUtils.directToCommodityDetail(context, commodityId)
}
override fun directToEnergyRecord(context: Context) {
DirectUtils.directToEnergyRecord(context)
}
override fun directToEnergyRulePage(context: Context) {
DirectUtils.directToEnergyRulePage(context)
}
override fun directToInviteFriends(context: Context) {
DirectUtils.directToInviteFriends(context)
}
override fun directToExchangeRulePage(context: Context) {
DirectUtils.directToExchangeRulePage(context)
}
override fun directToExchangeCommodityPage(context: Context) {
DirectUtils.directToExchangeCommodityPage(context)
}
override fun directToLotteryParadisePage(context: Context) {
DirectUtils.directToLotteryParadisePage(context)
}
override fun directDouyin(context: Context, userId: String) {
DirectUtils.directDouyin(context, userId)
}
@ -55,20 +83,39 @@ class DirectProviderImpl : IDirectProvider {
articleId: String?,
communityId: String?,
entrance: String?,
path: String?,
sourceEntrance: String
path: String?
) {
DirectUtils.directToCommunityArticle(context, articleId, communityId, entrance, path, sourceEntrance)
DirectUtils.directToCommunityArticle(context, articleId, communityId, entrance, path)
}
override fun directToVideoDetail(context: Context, videoId: String, entrance: String?, path: String?, sourceEntrance: String) {
DirectUtils.directToVideoDetail(context, videoId, entrance, path, sourceEntrance)
override fun directToVideoDetail(context: Context, videoId: String, entrance: String?, path: String?) {
DirectUtils.directToVideoDetail(context, videoId, entrance, path)
}
override fun directToAmway(context: Context, fixedTopAmwayCommentId: String?, entrance: String?, path: String?) {
DirectUtils.directToAmway(context, fixedTopAmwayCommentId, entrance, path)
}
override fun directToOrderCenter(context: Context) {
DirectUtils.directToOrderCenter(context)
}
override fun directToOrderDetail(context: Context, orderId: String) {
DirectUtils.directToOrderDetail(context, orderId)
}
override fun directToEnergyRecord(context: Context, position: Int) {
DirectUtils.directToEnergyRecord(context, position)
}
override fun directToMyPrizePage(context: Context) {
DirectUtils.directToMyPrizePage(context)
}
override fun directToWinOrderDetail(context: Context, orderId: String, activityId: String) {
DirectUtils.directToWinOrderDetail(context, orderId, activityId)
}
override fun directToQGame(context: Context) {
return DirectUtils.directToQGameHome(context)
}

View File

@ -9,7 +9,6 @@ import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.entity.GameUpdateEntity
import com.gh.gamecenter.feature.entity.CustomPageTrackData
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.provider.IDownloadButtonClickedProvider
@ -30,7 +29,6 @@ class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider {
var gameSchemaType = ""
var packageName = ""
var exposureSourceList: List<ExposureSource>? = null
var customPageTrackData: CustomPageTrackData? = null
val boundedObject = downloadButton.getObject()
@ -57,7 +55,6 @@ class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider {
gameSchemaType = boundedObject.gameBitChinese
packageName = boundedObject.getUniquePackageName() ?: ""
exposureSourceList = boundedObject.exposureEvent?.source
customPageTrackData = boundedObject.customPageTrackData
}
is GameUpdateEntity -> {
@ -83,13 +80,11 @@ class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider {
// 上报 UI 状态为启动的点击事件 (样式为启动,或者文案包含启动都算能启动)
if (downloadButton.buttonStyle == DownloadButton.ButtonStyle.LAUNCH_OR_OPEN
|| downloadButton.text.contains("启动")
) {
|| downloadButton.text.contains("启动")) {
// boundedObject 里找不到游戏类型时,尝试从已安装列表中获取
if (gameCategory.isEmpty() && packageName.isNotEmpty()) {
gameCategory =
PackageRepository.gameInstalled.find { it.packageName == packageName }?.category ?: ""
gameCategory = PackageRepository.gameInstalled.find { it.packageName == packageName }?.category ?: ""
}
NewFlatLogUtils.logGameLaunchButtonClicked(
@ -103,8 +98,7 @@ class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider {
// 预约状态不上报
if (downloadButton.buttonStyle == DownloadButton.ButtonStyle.NORMAL
|| downloadButton.buttonStyle == DownloadButton.ButtonStyle.PLUGIN
) {
|| downloadButton.buttonStyle == DownloadButton.ButtonStyle.PLUGIN) {
val text = downloadButton.text.ifEmpty {
downloadButton.getTag(R.string.download) ?: ""
@ -117,7 +111,6 @@ class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider {
}
// 上报神策点击事件
val customPageKV = customPageTrackData?.toKV() ?: arrayOf()
SensorsBridge.trackEventWithExposureSource(
"DownLoadbuttonClick",
exposureSourceList,
@ -134,7 +127,6 @@ class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider {
"last_page_name", GlobalActivityManager.getLastPageEntity().pageName,
"last_page_id", GlobalActivityManager.getLastPageEntity().pageId,
"last_page_business_id", GlobalActivityManager.getLastPageEntity().pageBusinessId,
*customPageKV
)
}
}

View File

@ -0,0 +1,19 @@
package com.gh.common.provider
import android.content.Context
import com.alibaba.android.arouter.facade.annotation.Route
import com.gh.common.util.GameSubstituteRepositoryHelper
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.core.provider.IGameSubstituteRepositoryProvider
@Route(path = RouteConsts.provider.gameSubstituteRepository, name = "GameSubstituteRepositoryHelper暴露服务")
class GameSubstituteRepositoryProviderImpl : IGameSubstituteRepositoryProvider {
override fun updateHistoricInstalledGameSet() {
GameSubstituteRepositoryHelper.updateHistoricInstalledGameSet()
}
override fun init(context: Context?) {
// Do nothing
}
}

View File

@ -2,15 +2,14 @@ package com.gh.common.provider
import android.content.Context
import com.alibaba.android.arouter.facade.annotation.Route
import com.gh.common.util.DirectUtils
import com.gh.gamecenter.MainActivity
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.core.provider.IMainProvider
@Route(path = RouteConsts.provider.mainActivity, name = "MainActivity暴露服务")
class MainProviderImpl : IMainProvider {
override fun skipToMainActivity(context: Context, type: String) {
DirectUtils.directToHomeDefaultTab(context)
override fun skipToMainActivity(context: Context, position: Int) {
MainActivity.skipToMainActivity(context, position)
}
override fun init(context: Context?) {

View File

@ -3,16 +3,14 @@ package com.gh.common.provider
import android.content.Context
import android.content.pm.PackageInfo
import com.alibaba.android.arouter.facade.annotation.Route
import com.gh.common.util.PackageHelper
import com.gh.common.util.PackageUtils
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.core.provider.IPackageUtilsProvider
import com.gh.gamecenter.core.utils.ProcessUtil
@Route(path = RouteConsts.provider.packageUtils, name = "PackageUtils暴露服务")
class PackageUtilsProviderImpl : IPackageUtilsProvider {
override fun obtainProcessName(): String? {
return ProcessUtil.getCurrentProcessName()
override fun obtainProcessName(context: Context): String? {
return PackageUtils.obtainProcessName(context)
}
override fun getGhVersionName(): String {
@ -24,7 +22,7 @@ class PackageUtilsProviderImpl : IPackageUtilsProvider {
}
override fun getInstalledPackages(context: Context, flag: Int): List<PackageInfo> {
return PackageHelper.getInstalledPackages(context, flag)
return PackageUtils.getInstalledPackages(context, flag)
}
override fun getApkSignatureByPackageName(context: Context, packageName: String): Array<String> {
@ -39,10 +37,6 @@ class PackageUtilsProviderImpl : IPackageUtilsProvider {
return PackageUtils.isSignedByGh(context, packageName)
}
override fun isInstalledWithLauncherIcon(context: Context, packageName: String): Boolean {
return PackageUtils.isInstalled(context, packageName)
}
override fun getInstalledTime(context: Context, packageName: String): Long {
return PackageUtils.getInstalledTime(context, packageName)
}

View File

@ -1,30 +1,16 @@
package com.gh.common.provider
import android.content.Context
import androidx.fragment.app.FragmentActivity
import android.os.Handler
import com.alibaba.android.arouter.facade.annotation.Route
import com.gh.common.util.DialogUtils
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.core.provider.IUpdateManagerProvider
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.update.UpdateHelper
import com.gh.gamecenter.manager.UpdateManager
@Route(path = RouteConsts.provider.updateManager, name = "UpdateManager暴露服务")
class UpdateManagerProviderImpl: IUpdateManagerProvider {
override fun checkUpdate(activity: FragmentActivity, ignoreSuppressOption: Boolean) {
val dialog = DialogUtils.showWaitDialog(activity, "检查更新中...")
UpdateHelper.getUpdate(ignoreSuppressOption) {
dialog.dismiss()
if (UpdateHelper.isUpdateValid(ignoreSuppressOption)) {
UpdateHelper.showUpdateDialog(activity) {
// Do nothing
}
} else {
ToastUtils.toast("您的光环助手已是最新版本")
}
}
override fun checkUpdate(context: Context, isAutoCheck: Boolean, handler: Handler?) {
UpdateManager.getInstance(context).checkUpdate(isAutoCheck, handler)
}
override fun init(context: Context?) {

View File

@ -20,14 +20,15 @@ import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.AppExecutor.uiExecutor
import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.entity.TrackableEntity
import com.gh.gamecenter.feature.entity.ApkEntity
import com.gh.gamecenter.feature.entity.SimulatorEntity
import com.gh.gamecenter.entity.TrackableEntity
import com.gh.ndownload.NDataChanger
import com.halo.assistant.HaloApp
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus
import com.lightgame.download.FileUtils
import com.lightgame.utils.Utils
import java.lang.ref.WeakReference
import java.text.DecimalFormat
@ -166,160 +167,162 @@ class SimulatorDownloadManager private constructor() {
this.gameName = gameName
this.gameType = gameCategoryChinese
PermissionHelper.checkGetInstalledAppsListBeforeAction(context) { _ ->
val isInstalledNewSimulator =
SimulatorGameManager.isNewSimulatorInstalled(HaloApp.getInstance().application)
//当没有安装新版本模拟器时候 判断是否隐藏
if (simulator?.active == false && !isInstalledNewSimulator) {
showNoneEmulatorDialog(context)
return@checkGetInstalledAppsListBeforeAction
}
var isInstalled = PackageUtils.isInstalledFromAllPackage(
context,
simulator?.apk?.packageName
)
//模拟器管理界面还是用之前的逻辑
if (isInstalledNewSimulator && location != SimulatorLocation.SIMULATOR_MANAGE) {
isInstalled = isInstalledNewSimulator
}
PermissionHelper.checkGetInstalledAppsListBeforeAction(context, object : EmptyCallback {
override fun onCallback() {
val isInstalledNewSimulator =
SimulatorGameManager.isNewSimulatorInstalled(HaloApp.getInstance().application)
//当没有安装新版本模拟器时候 判断是否隐藏
if (simulator?.active == false && !isInstalledNewSimulator) {
showNoneEmulatorDialog(context)
return
}
var isInstalled = PackageUtils.isInstalledFromAllPackage(
context,
simulator?.apk?.packageName
)
//模拟器管理界面还是用之前的逻辑
if (isInstalledNewSimulator && location != SimulatorLocation.SIMULATOR_MANAGE) {
isInstalled = isInstalledNewSimulator
}
// val versionFromInstalledApp = PackageUtils.getVersionNameByPackageName(simulator?.apk?.packageName)
val shouldShowUpdate =
PackageUtils.isInstalledApkMatchedMd5(simulator?.apk?.packageName, simulator?.apk?.md5)
val showAlertTag = SPUtils.getString(SimulatorGameManager.SIMULATOR_UPDATE_SHOW_ALERT_TAG, "") //当天是否弹过
val todayIsShow = showAlertTag == TimeUtils.getToday()
downloadType = if (shouldShowUpdate && isInstalled) "update" else "download"
if (downloadType == "update" && todayIsShow && location != SimulatorLocation.SIMULATOR_MANAGE) {
return@checkGetInstalledAppsListBeforeAction
}
if (downloadType == "download" && isInstalled) {
return@checkGetInstalledAppsListBeforeAction
}
val title = if (shouldShowUpdate && isInstalled) "更新模拟器" else "安装模拟器"
val message =
if (shouldShowUpdate && isInstalled) "检测到模拟器存在更高版本,是否前往更新" else "模拟器游戏需要先下载安装对应的模拟器,才可以运行"
val positiveText =
if (shouldShowUpdate && isInstalled) "更新(${simulator?.apk?.size}" else "下载(${simulator?.apk?.size}"
val negativeText = if (shouldShowUpdate && isInstalled) "下次再说" else "取消"
val trackableEntity = TrackableEntity(
"模拟器下载",
key = if (shouldShowUpdate && isInstalled) "更新弹窗" else "下载弹窗",
logShowEvent = true
)
if (shouldShowUpdate && isInstalled) {
NewFlatLogUtils.logSimulatorUpdateAlertShow()
}
if (shouldShowUpdate && isInstalled) {
SensorsBridge.trackSimulatorUpdateDialogShow(
gameId = gameId,
gameName = gameName,
gameType = gameCategoryChinese,
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
val shouldShowUpdate =
PackageUtils.isInstalledApkMatchedMd5(simulator?.apk?.packageName, simulator?.apk?.md5)
val showAlertTag = SPUtils.getString(SimulatorGameManager.SIMULATOR_UPDATE_SHOW_ALERT_TAG, "") //当天是否弹过
val todayIsShow = showAlertTag == TimeUtils.getToday()
downloadType = if (shouldShowUpdate && isInstalled) "update" else "download"
if (downloadType == "update" && todayIsShow && location != SimulatorLocation.SIMULATOR_MANAGE) {
return
}
if (downloadType == "download" && isInstalled) {
return
}
val title = if (shouldShowUpdate && isInstalled) "更新模拟器" else "安装模拟器"
val message =
if (shouldShowUpdate && isInstalled) "检测到模拟器存在更高版本,是否前往更新" else "模拟器游戏需要先下载安装对应的模拟器,才可以运行"
val positiveText =
if (shouldShowUpdate && isInstalled) "更新(${simulator?.apk?.size}" else "下载(${simulator?.apk?.size}"
val negativeText = if (shouldShowUpdate && isInstalled) "下次再说" else "取消"
val trackableEntity = TrackableEntity(
"模拟器下载",
key = if (shouldShowUpdate && isInstalled) "更新弹窗" else "下载弹窗",
logShowEvent = true
)
} else {
SensorsBridge.trackSimulatorInstallDialogShow(
gameId = gameId,
gameName = gameName,
gameType = gameCategoryChinese,
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
)
}
DialogHelper.showDialog(
context,
title,
message,
positiveText,
negativeText,
trackMtaEvent = true,
cancelClickCallback = {
if (shouldShowUpdate && isInstalled) {
cancelCallback?.invoke()
NewFlatLogUtils.logSimulatorUpdateAlertClick("取消")
MtaHelper.onEvent(trackableEntity.event, trackableEntity.key, "点击下次再说")
SensorsBridge.trackSimulatorUpdateDialogClick(
buttonName = negativeText,
gameId = gameId,
gameName = gameName,
gameType = gameCategoryChinese,
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
)
} else {
SensorsBridge.trackSimulatorInstallDialogClick(
buttonName = negativeText,
gameId = gameId,
gameName = gameName,
gameType = gameCategoryChinese,
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
)
}
},
confirmClickCallback = {
showDownloadingDialog(context, simulator, gameId, gameName, gameCategoryChinese)
NewFlatLogUtils.logSimulatorUpdateAlertClick("更新")
MtaHelper.onEvent(
trackableEntity.event,
trackableEntity.key,
if (shouldShowUpdate && isInstalled) "点击更新" else "点击下载"
if (shouldShowUpdate && isInstalled) {
NewFlatLogUtils.logSimulatorUpdateAlertShow()
}
if (shouldShowUpdate && isInstalled) {
SensorsBridge.trackSimulatorUpdateDialogShow(
gameId = gameId,
gameName = gameName,
gameType = gameCategoryChinese,
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
)
if (shouldShowUpdate && isInstalled) {
SensorsBridge.trackSimulatorUpdateDialogClick(
buttonName = positiveText,
gameId = gameId,
gameName = gameName,
gameType = gameCategoryChinese,
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
} else {
SensorsBridge.trackSimulatorInstallDialogShow(
gameId = gameId,
gameName = gameName,
gameType = gameCategoryChinese,
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
)
}
DialogHelper.showDialog(
context,
title,
message,
positiveText,
negativeText,
trackMtaEvent = true,
cancelClickCallback = {
if (shouldShowUpdate && isInstalled) {
cancelCallback?.invoke()
NewFlatLogUtils.logSimulatorUpdateAlertClick("取消")
MtaHelper.onEvent(trackableEntity.event, trackableEntity.key, "点击下次再说")
SensorsBridge.trackSimulatorUpdateDialogClick(
buttonName = negativeText,
gameId = gameId,
gameName = gameName,
gameType = gameCategoryChinese,
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
)
} else {
SensorsBridge.trackSimulatorInstallDialogClick(
buttonName = negativeText,
gameId = gameId,
gameName = gameName,
gameType = gameCategoryChinese,
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
)
}
},
confirmClickCallback = {
showDownloadingDialog(context, simulator, gameId, gameName, gameCategoryChinese)
NewFlatLogUtils.logSimulatorUpdateAlertClick("更新")
MtaHelper.onEvent(
trackableEntity.event,
trackableEntity.key,
if (shouldShowUpdate && isInstalled) "点击更新" else "点击下载"
)
} else {
SensorsBridge.trackSimulatorInstallDialogClick(
buttonName = positiveText,
gameId = gameId,
gameName = gameName,
gameType = gameCategoryChinese,
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
)
}
},
touchOutsideCallback = {
if (shouldShowUpdate && isInstalled) {
SensorsBridge.trackSimulatorUpdateDialogClick(
buttonName = "关闭弹窗",
gameId = gameId,
gameName = gameName,
gameType = gameCategoryChinese,
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
)
} else {
SensorsBridge.trackSimulatorInstallDialogClick(
buttonName = "关闭弹窗",
gameId = gameId,
gameName = gameName,
gameType = gameCategoryChinese,
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
)
}
},
mtaEvent = trackableEntity.event, mtaKey = trackableEntity.key,
extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
)
if (downloadType == "update" && location != SimulatorLocation.SIMULATOR_MANAGE) {
SPUtils.setString(SimulatorGameManager.SIMULATOR_UPDATE_SHOW_ALERT_TAG, TimeUtils.getToday())
if (shouldShowUpdate && isInstalled) {
SensorsBridge.trackSimulatorUpdateDialogClick(
buttonName = positiveText,
gameId = gameId,
gameName = gameName,
gameType = gameCategoryChinese,
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
)
} else {
SensorsBridge.trackSimulatorInstallDialogClick(
buttonName = positiveText,
gameId = gameId,
gameName = gameName,
gameType = gameCategoryChinese,
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
)
}
},
touchOutsideCallback = {
if (shouldShowUpdate && isInstalled) {
SensorsBridge.trackSimulatorUpdateDialogClick(
buttonName = "关闭弹窗",
gameId = gameId,
gameName = gameName,
gameType = gameCategoryChinese,
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
)
} else {
SensorsBridge.trackSimulatorInstallDialogClick(
buttonName = "关闭弹窗",
gameId = gameId,
gameName = gameName,
gameType = gameCategoryChinese,
lastPageId = GlobalActivityManager.getLastPageEntity().pageId,
lastPageName = GlobalActivityManager.getLastPageEntity().pageName,
lastPageBusinessId = GlobalActivityManager.getLastPageEntity().pageBusinessId
)
}
},
mtaEvent = trackableEntity.event, mtaKey = trackableEntity.key,
extraConfig = DialogHelper.Config(centerTitle = true, centerContent = true)
)
if (downloadType == "update" && location != SimulatorLocation.SIMULATOR_MANAGE) {
SPUtils.setString(SimulatorGameManager.SIMULATOR_UPDATE_SHOW_ALERT_TAG, TimeUtils.getToday())
}
}
}
})
}
fun showDownloadingDialog(

View File

@ -8,6 +8,7 @@ import android.graphics.Bitmap
import android.net.Uri
import android.text.TextUtils
import com.gh.common.constant.Config
import com.gh.gamecenter.feature.utils.ApkActiveUtils
import com.gh.common.util.LogUtils
import com.gh.common.util.PackageUtils
import com.gh.download.DownloadManager
@ -23,13 +24,13 @@ import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.core.utils.UrlFilterUtils
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.SimulatorGameRecordEntity
import com.gh.gamecenter.feature.utils.ApkActiveUtils
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.room.AppDatabase
import com.halo.assistant.HaloApp
import com.lightgame.download.DownloadDao
import com.lightgame.download.DownloadEntity
import com.lightgame.download.FileUtils
import com.lightgame.utils.AppManager
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
@ -38,6 +39,7 @@ import okhttp3.ResponseBody
import org.json.JSONArray
import java.io.ByteArrayOutputStream
import java.io.File
import java.util.*
object SimulatorGameManager {
@ -183,8 +185,8 @@ object SimulatorGameManager {
val intent = Intent()
intent.data = Uri.fromFile(File(downloadEntity.path))
if (gameEntity.simulatorType == "FBA" || gameEntity.simulatorType == "FBN") {
val apkEntity = gameEntity.getApk().firstOrNull()
intent.putExtra("rom_name", apkEntity?.packageName ?: "")
val apkEntity = gameEntity.getApk()[0]
intent.putExtra("rom_name", apkEntity.packageName)
}
intent.putExtra("default_path", downloadEntity.path.substring(0, downloadEntity.path.lastIndexOf('/')))
intent.putExtra("game_type", gameEntity.simulatorType)

View File

@ -50,8 +50,6 @@ object ArchiveDownloadButtonHelper {
}
downloadBtn.setOnClickListener {
when {
// 检查是否已安装畅玩助手
!VHelper.isVSpaceInstalled(context) -> showVSpaceTipDialog(context, gameEntity)
// 检查是否已安装游戏
!VHelper.isInstalled(packageName) -> {
// 检查游戏是否在安装中

View File

@ -1,11 +1,17 @@
package com.gh.common.util;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import com.gh.gamecenter.common.constant.EntranceConsts;
import com.gh.gamecenter.core.utils.CurrentActivityHolder;
import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.login.utils.QuickLoginHelper;
import com.gh.gamecenter.login.view.LoginActivity;
import com.gh.gamecenter.common.utils.NetworkUtils;
import com.gh.gamecenter.core.utils.SPUtils;
import com.gh.gamecenter.login.user.UserManager;
import com.lightgame.utils.Utils;
@ -22,15 +28,15 @@ public class CheckLoginUtils {
LogUtils.login("dialog", null, entrance);
LogUtils.login("activity", null, entrance);
// if (SPUtils.getBoolean(Constants.SP_HAS_GET_PHONE_INFO) || NetworkUtils.isOpenMobileData(context)) {
// startQuickLogin(context, entrance);
// } else {
// 有可能App未启动
Bundle bundle = new Bundle();
bundle.putString(EntranceConsts.KEY_ENTRANCE, entrance);
bundle.putString(EntranceConsts.KEY_TO, LoginActivity.class.getName());
EntranceUtils.jumpActivity(context, bundle);
// }
if (SPUtils.getBoolean(Constants.SP_HAS_GET_PHONE_INFO) || NetworkUtils.isOpenMobileData(context)) {
startQuickLogin(context, entrance);
} else {
// 有可能App未启动
Bundle bundle = new Bundle();
bundle.putString(EntranceConsts.KEY_ENTRANCE, entrance);
bundle.putString(EntranceConsts.KEY_TO, LoginActivity.class.getName());
EntranceUtils.jumpActivity(context, bundle);
}
} else {
if (listener != null) {
listener.onLogin();
@ -38,16 +44,16 @@ public class CheckLoginUtils {
}
}
// private static void startQuickLogin(Context context, String entrance) {
// // 需要确保传入的 context 不为 application
// if (!(context instanceof Activity)) {
// context = CurrentActivityHolder.getCurrentActivity();
// }
//
// if (context != null) {
// QuickLoginHelper.startLogin(context, entrance);
// }
// }
private static void startQuickLogin(Context context, String entrance) {
// 需要确保传入的 context 不为 application
if (!(context instanceof Activity)) {
context = CurrentActivityHolder.getCurrentActivity();
}
if (context != null) {
QuickLoginHelper.startLogin(context, entrance);
}
}
public static void checkLogin(final Context context, Bundle nextToBundle, boolean isTriggerNextStep, String entrance, OnLoginListener listener) {
if (!isLogin()) {

View File

@ -533,7 +533,7 @@ public class CommentUtils {
} else {
ImageUtils.display(holder.commentUserBadgeIv, "");
}
ImageUtils.display(holder.commentUserIconDv, userInfo.getIcon());
ImageUtils.displayIcon(holder.commentUserIconDv, userInfo.getIcon());
} else {
if (entity.getMe() != null && entity.getMe().isContentOwner()) {
holder.commentAuthorTv.setVisibility(View.VISIBLE);
@ -549,7 +549,7 @@ public class CommentUtils {
if (TextUtils.isEmpty(entity.getUser().getIcon())) {
ImageUtils.display(holder.commentUserIconDv, R.drawable.user_default_icon_comment);
} else {
ImageUtils.display(holder.commentUserIconDv, entity.getUser().getIcon());
ImageUtils.displayIcon(holder.commentUserIconDv, entity.getUser().getIcon());
}
}
}

View File

@ -18,6 +18,7 @@ import com.gh.gamecenter.common.eventbus.EBReuse;
import com.gh.gamecenter.common.exposure.meta.MetaUtil;
import com.gh.gamecenter.common.retrofit.BiResponse;
import com.gh.gamecenter.common.utils.ExtensionsKt;
import com.gh.gamecenter.common.utils.SensorsBridge;
import com.gh.gamecenter.core.utils.GsonUtils;
import com.gh.gamecenter.core.utils.MtaHelper;
import com.gh.gamecenter.core.utils.SPUtils;
@ -125,7 +126,14 @@ public class DataUtils {
HaloApp.getInstance().setGid(gid);
// 更新广告配置
AdDelegateHelper.INSTANCE.requestAdConfig(false, "", null);
ExtensionsKt.doOnMainProcessOnly(HaloApp.getInstance(), () -> {
AdDelegateHelper.INSTANCE.requestAdConfig(false, "", null);
});
// 避免重复调用
if (!TextUtils.isEmpty(gid)) {
GameSubstituteRepositoryHelper.updateHistoricInstalledGameSet();
}
getDeviceCertification(gid);
@ -145,8 +153,7 @@ public class DataUtils {
@Override
public void onFailure(String s) {
// 更新广告配置
AdDelegateHelper.INSTANCE.requestAdConfig(false, "", null);
MtaHelper.onEventWithBasicDeviceInfo("开发辅助", "GID 获取异常", s);
}
});
}
@ -193,8 +200,9 @@ public class DataUtils {
RealNameHelper.updateCertificationStatus(0);
}
RealNameHelper.INSTANCE.onRealNameInfoUpdated();
EventBus.getDefault().post(new EBReuse(Constants.EB_REALNAME_RESULT));
// new GhContentProvider().localInsert( HaloApp.getInstance().getApplication(),values);
try {
// Unknown URL content://com.gh.gamecenter.provider/certification
// TODO 将 com.gh.gamecenter 改成 BuildConfig.ApplicationID

View File

@ -1,80 +0,0 @@
package com.gh.common.util
import android.view.animation.AlphaAnimation
import android.view.animation.Animation
import android.view.animation.ScaleAnimation
import android.widget.TextView
import com.gh.common.constant.Config
/**
* 光环游戏搜索栏默认文案轮换
*/
object DefaultSearchHintHelper {
private val hintList = ArrayList<String>()
init {
loadData()
}
fun loadData() {
hintList.clear()
Config.getSettings()?.search?.defaultData?.also {
if (it.isNotEmpty()) {
for (h in it) {
hintList.add(h.removeSuffix("."))
}
}
}
}
fun setSearchHint(searchTv: TextView) {
var hintIndex = 0
val scaleAnimation = ScaleAnimation(
0.4F, 1.0F, 0.4F, 1.0F,
Animation.RELATIVE_TO_SELF, 0.5F, Animation.RELATIVE_TO_SELF, 0.5F
)
scaleAnimation.duration = 500
val alphaAnimation = AlphaAnimation(1F, 0.2F)
alphaAnimation.duration = 300
alphaAnimation.startOffset = 5000
scaleAnimation.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) {}
override fun onAnimationEnd(animation: Animation) {
searchTv.animation = alphaAnimation
alphaAnimation.start()
}
override fun onAnimationRepeat(animation: Animation) {}
})
alphaAnimation.setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationStart(animation: Animation) {}
override fun onAnimationEnd(animation: Animation) {
// 切换数据
if (hintList.isNotEmpty()) {
if (hintIndex > hintList.size - 1) {
hintIndex = 0
}
searchTv.hint = hintList[hintIndex]
hintIndex++
searchTv.animation = scaleAnimation
scaleAnimation.start()
}
}
override fun onAnimationRepeat(animation: Animation) {}
})
if (hintList.isEmpty()) {
loadData()
}
if (hintList.isNotEmpty()) {
if (hintList.size > 1) {
searchTv.animation = alphaAnimation
} else {
val hint = hintList[0]
searchTv.hint = hint
}
}
}
}

View File

@ -12,6 +12,9 @@ import com.gh.common.repository.ReservationRepository;
import com.gh.common.simulator.SimulatorGameManager;
import com.gh.common.xapk.XapkInstaller;
import com.gh.common.xapk.XapkUnzipStatus;
import com.gh.gamecenter.feature.entity.GameEntity;
import com.gh.gamecenter.feature.entity.PluginLocation;
import com.gh.gamecenter.feature.view.DownloadButton;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.R;
import com.gh.gamecenter.adapter.viewholder.DetailViewHolder;
@ -19,9 +22,6 @@ import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.common.entity.LinkEntity;
import com.gh.gamecenter.common.utils.ExtensionsKt;
import com.gh.gamecenter.core.utils.SPUtils;
import com.gh.gamecenter.feature.entity.GameEntity;
import com.gh.gamecenter.feature.entity.PluginLocation;
import com.gh.gamecenter.feature.view.DownloadButton;
import com.gh.gamecenter.manager.PackagesManager;
import com.gh.vspace.VHelper;
import com.lightgame.download.DownloadEntity;
@ -259,7 +259,7 @@ public class DetailDownloadUtils {
if (showDualDownloadButton && viewHolder.getLocalDownloadSizeTv() != null) {
viewHolder.getLocalDownloadSizeTv().setVisibility(View.GONE);
String size = viewHolder.getGameEntity().getApk().isEmpty() ? "" : viewHolder.getGameEntity().getApk().get(0).getSize();
String size = viewHolder.getGameEntity().getApk().get(0).getSize();
if (size != null) {
String sizeWithoutDigit = size.replaceAll("(?<=\\d)\\.[0-9]+(?!\\d)", "");
viewHolder.getLocalDownloadSizeTv().setText(sizeWithoutDigit);
@ -367,7 +367,8 @@ public class DetailDownloadUtils {
String downloadAddWord = gameEntity.getDownloadAddWord();
// 不满足条件的部分游戏隐藏下载按钮
if (!"光环助手".equals(gameEntity.getName())) {
if (Config.isShowDownload(gameEntity.getId())
&& !"光环助手".equals(gameEntity.getName())) {
viewHolder.getDownloadBottom().setVisibility(View.VISIBLE);
} else {
viewHolder.getDownloadBottom().setVisibility(View.GONE);
@ -442,7 +443,7 @@ public class DetailDownloadUtils {
}
private static String getDownloadSizeText(DetailViewHolder viewHolder) {
return String.format("%s", viewHolder.getGameEntity().getApk().isEmpty() ? "" : viewHolder.getGameEntity().getApk().get(0).getSize());
return String.format("%s", viewHolder.getGameEntity().getApk().get(0).getSize());
}
private static void updateVStyleDownloadButton(DetailViewHolder viewHolder,

View File

@ -1,17 +1,23 @@
package com.gh.common.util
import android.content.Context
import android.os.Environment
import android.preference.PreferenceManager
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.exposure.meta.MetaUtil
import com.gh.gamecenter.BuildConfig
import com.gh.gamecenter.entity.TimeEntity
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import java.io.File
object DeviceTokenUtils {
const val DEVICE_ID = "uuid"
// 同步服务器时间
@JvmStatic
@Synchronized
@ -33,29 +39,99 @@ object DeviceTokenUtils {
}
@JvmStatic
fun getLaunchType(): LunchType {
fun getLaunchType(readOnly: Boolean = false): LunchType {
var lunchType: LunchType? = null
val values = PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().application).all
// 版本更新
if (values.isNotEmpty()) {
for (value in values) {
if (value.key.contains(Constants.SP_NEW_FIRST_LAUNCH_VERSION)) {
if (value.key.contains("isNewFirstLaunchV")) {
lunchType = LunchType.UPDATE
break
}
}
}
// 再次重装
if (lunchType == null && !getDeviceId().isNullOrEmpty()) {
lunchType = LunchType.AGAIN
}
// 首次安装
if (lunchType == null) {
lunchType = LunchType.FIRST
}
// 保存deviceId
var deviceId = MetaUtil.getIMEI()
if (deviceId.isNullOrEmpty()) {
deviceId = Utils.getTime(HaloApp.getInstance().application).toString()
}
if (!readOnly) {
setDeviceId(deviceId)
}
return lunchType
}
private fun getDeviceFileList(): List<File> {
val sdCardDir = Environment.getExternalStorageDirectory()
val fileList: MutableList<File> = ArrayList()
fileList.add(File(sdCardDir.path + "/gh-uuid/$DEVICE_ID"))
fileList.add(File(sdCardDir.path + "/system/$DEVICE_ID"))
fileList.add(File(sdCardDir.path + "/data/$DEVICE_ID"))
return fileList
}
@Synchronized
private fun setDeviceId(deviceId: String) {
//将deviceId存到sp
val sp = PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().application)
val edit = sp.edit()
edit.putString(DEVICE_ID, deviceId)
edit.apply()
Utils.log("saveDeviceId", "保存成功SP")
//将deviceId存到SD卡
for (file in getDeviceFileList()) {
try {
val parentFile = file.parentFile
if (!parentFile.exists()) parentFile.mkdirs()
file.writeText(deviceId)
Utils.log("saveDeviceId", "保存成功SDCard目录为${file.path}")
} catch (e: Exception) {
Utils.log("保存u${DEVICE_ID}到SDCard异常${file.path} " + e.toString())
e.printStackTrace()
}
}
}
private fun getDeviceId(): String? {
val sp = PreferenceManager.getDefaultSharedPreferences(HaloApp.getInstance().application)
var deviceId = sp.getString(DEVICE_ID, null)
if (deviceId.isNullOrEmpty()) {
val fileList = getDeviceFileList()
for (file in fileList) {
if (file.exists()) {
try {
deviceId = file.readText()
Utils.log("getDeviceId", "获取成功DataFile$DEVICE_ID")
return deviceId
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
if (BuildConfig.DEBUG) {
Utils.log("getDeviceId", "获取成功SP$DEVICE_ID")
}
return deviceId
}
}
enum class LunchType {
FIRST,
UPDATE
UPDATE,
AGAIN
}

View File

@ -82,7 +82,6 @@ import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import kotlin.Unit;
import kotlin.collections.CollectionsKt;
import kotlin.jvm.functions.Function0;
public class DialogUtils {
@ -579,15 +578,11 @@ public class DialogUtils {
dialog.dismiss();
});
ApkEntity apkEntity = CollectionsKt.firstOrNull(gameEntity.getApk());
String size = apkEntity == null ? "" : apkEntity.getSize();
if ("show&download".equals(gameEntity.getOverseasAddressDialog().getStatus())) {
if (apkEntity != null) {
apkEntity.setUrl(gameEntity.getOverseasAddressDialog().getLink());
}
gameEntity.getApk().get(0).setUrl(gameEntity.getOverseasAddressDialog().getLink());
}
binding.urlTv.setText(gameEntity.getOverseasAddressDialog().getLink());
binding.downloadBtn.setText("下载(" + size + "");
binding.downloadBtn.setText("下载(" + gameEntity.getApk().get(0).getSize() + "");
binding.downloadBtn.setOnClickListener(v -> {
dismissByTouchInside.set(true);
SensorsBridge.trackOverseasAddressDialogClick(
@ -636,12 +631,7 @@ public class DialogUtils {
binding.closeIv.setOnClickListener(v -> dialog.dismiss());
binding.urlTv.setText(gameEntity.getLandPageAddressDialog().getLink());
String downloadText = gameEntity.isLandPageAddressDialogShowOnly()
? "下载(" + gameEntity.getApk().get(0).getSize() + ""
: context.getString(R.string.dialog_land_page_address_confirm);
binding.downloadBtn.setText(downloadText);
binding.downloadBtn.setText(context.getString(R.string.dialog_land_page_address_confirm));
binding.downloadBtn.setOnClickListener(v -> {
listener.onConfirm();
dialog.dismiss();

View File

@ -33,22 +33,29 @@ import com.gh.gamecenter.common.entity.*
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.core.provider.IQGameProvider
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.discovery.DiscoveryActivity
import com.gh.gamecenter.download.DownloadFragment.Companion.INDEX_UPDATE
import com.gh.gamecenter.entity.*
import com.gh.gamecenter.entity.GameCollectionListEntity
import com.gh.gamecenter.entity.SubjectData
import com.gh.gamecenter.entity.SubjectRecommendEntity
import com.gh.gamecenter.entity.VideoLinkEntity
import com.gh.gamecenter.eventbus.EBSkip
import com.gh.gamecenter.feature.entity.GameDetailServer
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.LibaoEntity
import com.gh.gamecenter.feature.entity.MeEntity
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.exposure.ExposureEvent.Companion.createEvent
import com.gh.gamecenter.feature.exposure.ExposureType
import com.gh.gamecenter.feature.provider.IConcernInfoProvider
import com.gh.gamecenter.forum.detail.ForumDetailActivity
import com.gh.gamecenter.forum.home.CommunityActivity
import com.gh.gamecenter.forum.home.CommunityHomeFragment
import com.gh.gamecenter.forum.search.ForumOrUserSearchActivity
import com.gh.gamecenter.fragment.MainWrapperFragment
import com.gh.gamecenter.game.columncollection.detail.ColumnCollectionDetailActivity
import com.gh.gamecenter.game.commoncollection.detail.CustomCommonCollectionDetailActivity
import com.gh.gamecenter.game.commoncollection.detail.CommonCollectionDetailActivity
import com.gh.gamecenter.game.upload.GameSubmissionActivity
import com.gh.gamecenter.gamecollection.detail.GameCollectionDetailActivity
import com.gh.gamecenter.gamecollection.hotlist.GameCollectionHotListActivity
@ -61,9 +68,7 @@ import com.gh.gamecenter.gamedetail.fuli.kaifu.ServersSubscribedGameListActivity
import com.gh.gamecenter.gamedetail.history.HistoryApkListActivity
import com.gh.gamecenter.gamedetail.rating.RatingReplyActivity
import com.gh.gamecenter.help.HelpAndFeedbackBridge
import com.gh.gamecenter.libao.LibaoDetailActivity
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.newsdetail.NewsDetailActivity
import com.gh.gamecenter.personalhome.UserHomeActivity
import com.gh.gamecenter.personalhome.background.PersonalityBackgroundActivity
import com.gh.gamecenter.personalhome.border.AvatarBorderActivity
@ -83,20 +88,19 @@ import com.gh.gamecenter.servers.gametest2.GameServerTestV2Activity
import com.gh.gamecenter.setting.SettingBridge
import com.gh.gamecenter.subject.SubjectActivity
import com.gh.gamecenter.tag.TagsActivity
import com.gh.gamecenter.toolbox.ToolBoxActivity
import com.gh.gamecenter.toolbox.ToolBoxBlockActivity
import com.gh.gamecenter.video.data.VideoDataActivity
import com.gh.gamecenter.video.detail.VideoDetailActivity
import com.gh.gamecenter.video.detail.VideoDetailContainerViewModel
import com.gh.gamecenter.video.game.GameVideoActivity
import com.gh.gamecenter.video.videomanager.VideoManagerActivity
import com.gh.gamecenter.wrapper.MainWrapperRepository
import com.gh.gamecenter.wrapper.ToolbarWrapperActivity
import com.gh.vspace.VDownloadManagerActivity
import com.halo.assistant.HaloApp
import com.halo.assistant.fragment.WebFragment
import com.lightgame.utils.Utils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import org.greenrobot.eventbus.EventBus
import retrofit2.HttpException
import java.net.URLEncoder
import java.util.*
@ -108,8 +112,8 @@ import kotlin.math.roundToInt
object DirectUtils {
@JvmStatic
fun directToLinkPage(context: Context, linkEntity: LinkEntity, entrance: String, path: String, sourceEntrance: String = "") {
directToLinkPage(context, linkEntity, entrance, path, null, sourceEntrance)
fun directToLinkPage(context: Context, linkEntity: LinkEntity, entrance: String, path: String) {
directToLinkPage(context, linkEntity, entrance, path, null)
}
@JvmStatic
@ -118,10 +122,9 @@ object DirectUtils {
linkEntity: LinkEntity,
entrance: String,
path: String,
exposureEvent: ExposureEvent? = null,
sourceEntrance: String = ""
exposureEvent: ExposureEvent? = null
) {
directToLinkPage(context, linkEntity, entrance, path, exposureEvent, null, sourceEntrance)
directToLinkPage(context, linkEntity, entrance, path, exposureEvent, null)
}
// 用于判断是否已经对接相关类型
@ -156,21 +159,7 @@ object DirectUtils {
"explore_column",
"game_explore",
"column_test_v2",
"game_list_collection",
"multi_tab_nav",
"custom_page",
"bottom_tab",
"qq_mini_game_column_detail",
"game_hot_list",
"libao_center",
"article_center",
"video_stream",
"libao",
"community_home",
"bbs_section",
"qa",
"feedback",
"toolkit"
"game_list_collection"
)
fun directToLinkPage(
@ -180,7 +169,6 @@ object DirectUtils {
path: String,
exposureEvent: ExposureEvent? = null,
unknownCallback: (() -> Unit)?,
sourceEntrance: String = ""
) {
when (linkEntity.type) {
"article", "news", "文章" -> {
@ -195,7 +183,6 @@ object DirectUtils {
if (exposureEvent != null) {
directToGameDetail(
context, linkEntity.link
?: "", linkEntity.text
?: "", BaseActivity.mergeEntranceAndPath(entrance, path), traceEvent = exposureEvent
)
} else {
@ -216,7 +203,7 @@ object DirectUtils {
"question", "社区问题" -> directToQuestionDetail(
context, linkEntity.link
?: "", entrance, path, sourceEntrance
?: "", entrance, path
)
"answer", "社区回答" -> directToAnswerDetail(context, linkEntity.link ?: "", entrance, path)
@ -231,8 +218,7 @@ object DirectUtils {
linkEntity.community!!,
linkEntity.link!!,
entrance,
path,
sourceEntrance,
path
)
"community_column", "社区专题" -> directToCommunityColumn(
@ -310,7 +296,6 @@ object DirectUtils {
"",
linkEntity.blockId,
linkEntity.blockName,
"",
exposureEvent
)
@ -320,21 +305,12 @@ object DirectUtils {
"wechat_bind" -> context.startActivity(WebActivity.getBindWechatIntent(context))
"video", "bbs_video", "视频" -> directToVideoDetail(
"video", "bbs_video", "video_stream", "视频" -> directToVideoDetail(
context,
videoId = linkEntity.link!!,
fromLocation = VideoDetailContainerViewModel.Location.VIDEO_CHOICENESS.value,
entrance = entrance,
path = path,
sourceEntrance = sourceEntrance
)
"video_stream" -> directToLegacyVideoDetail(
context,
"",
VideoDetailContainerViewModel.Location.VIDEO_ACTIVITY.value,
referer = "视频流-$entrance",
isHomeVideo = true
path = path
)
"game_video" -> directToGameVideo(context, linkEntity.link ?: "", entrance, path)
@ -407,17 +383,17 @@ object DirectUtils {
"setting" -> context.startActivity(SettingBridge.getSettingIntent(context, false, entrance))
"index_page" -> directToHomeDefaultTab(context)
"index_page" -> directToHomeTab(context)
"video_upload" -> context.startActivity(VideoManagerActivity.getIntent(context, "", entrance))
"bbs", "community_home" -> directToHomeCommunityTab(context)
"bbs" -> directToForum(context)
"user_page" -> directToHomeActivity(context, UserManager.getInstance().userId, "", entrance)
"video_tab" -> directToHomeVideoTab(context)
"video_tab" -> directToVideoTab(context)
"toolkit" -> context.startActivity(ToolBoxActivity.getIntent(context, entrance))
"toolkit" -> context.startActivity(ToolBoxBlockActivity.getIntent(context, entrance))
"column_test" -> context.startActivity(
GameServerTestActivity.getIntent(
@ -438,7 +414,7 @@ object DirectUtils {
} ?: ""
}
"halo_tab" -> directToHomeMyHaloTab(context)
"halo_tab" -> directToPersonalTab(context)
"common_collection" -> directToCommonCollectionDetail(
context,
@ -477,29 +453,6 @@ object DirectUtils {
"qq_mini_game_column" -> directToQGameHome(context)
// QQ游戏专题详情页
"qq_mini_game_column_detail" -> {
directToSubject(
context = context,
id = linkEntity.link ?: "",
subjectName = linkEntity.text,
entrance = BaseActivity.mergeEntranceAndPath(entrance, path),
exposureEvent = exposureEvent,
isQQMiniGame = true
)
}
// 资讯中心
"article_center" -> {
context.startActivity(InfoActivity.getIntent(context))
}
// 礼包中心
"libao_center" -> {
directToGift(context, entrance)
}
"game_hot_list" -> directToGameCollectionHotList(context, entrance)
"game_list_collection" -> directToGameCollectionListDetail(
context,
linkEntity.link ?: "",
@ -508,34 +461,6 @@ object DirectUtils {
entrance
)
"multi_tab_nav" -> context.startActivity(
ToolbarWrapperActivity.getMultiTabNavIntent(
context,
linkEntity.link ?: "",
linkEntity.text ?: ""
)
)
"custom_page" -> context.startActivity(
ToolbarWrapperActivity.getCustomPageIntent(
context,
linkEntity.link ?: "",
linkEntity.text ?: ""
)
)
// 选中首页底部 tab
"bottom_tab" -> {
val intent = Intent(context, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
}
context.startActivity(intent)
if (linkEntity is LaunchRedirect) {
MainWrapperRepository.getInstance().sendSelectTabEvent(linkEntity)
}
}
"" -> {
// do nothing
}
@ -590,9 +515,7 @@ object DirectUtils {
columnName: String = "",
blockId: String = "",
blockName: String = "",
style: String = "",
exposureEvent: ExposureEvent? = null,
showSubjectTab: Boolean = false
exposureEvent: ExposureEvent? = null
) {
if (id.isEmpty()) return
val bundle = Bundle()
@ -602,9 +525,7 @@ object DirectUtils {
bundle.putString(KEY_COLUMNNAME, columnName)
bundle.putString(KEY_BLOCK_ID, blockId)
bundle.putString(KEY_BLOCK_NAME, blockName)
bundle.putString(KEY_COLUMN_COLLECTION_STYLE, style)
bundle.putInt(KEY_POSITION, position)
bundle.putBoolean(KEY_SHOW_SUBJECT_TAB, showSubjectTab)
if (exposureEvent != null) {
bundle.putParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST, ArrayList(exposureEvent.source))
}
@ -659,7 +580,7 @@ object DirectUtils {
if (id.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_TO, NewsDetailActivity::class.java.name)
bundle.putString(KEY_TO, NewsDetailActivity::class.java.simpleName)
bundle.putString(KEY_NEWSID, id)
if (entrance?.contains("隐私政策") == true) {
bundle.putBoolean(KEY_HIDE_USELESS_INFO, true)
@ -675,7 +596,7 @@ object DirectUtils {
if (id.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_TO, NewsDetailActivity::class.java.name)
bundle.putString(KEY_TO, NewsDetailActivity::class.java.simpleName)
bundle.putString(KEY_NEWSID, id)
bundle.putBoolean(KEY_HIDE_USELESS_INFO, hideUselessInfo)
jumpActivity(context, bundle)
@ -754,7 +675,6 @@ object DirectUtils {
fun directToGameDetail(
context: Context,
id: String,
name: String = "",
entrance: String? = null,
autoDownload: Boolean? = null,
tab: String? = "",
@ -774,7 +694,7 @@ object DirectUtils {
}
}
if (traceEvent != null) {
val clickEvent = createEvent(GameEntity(id = id, name = name), traceEvent.source, appendTrace(traceEvent), ExposureType.CLICK)
val clickEvent = createEvent(GameEntity(id), traceEvent.source, appendTrace(traceEvent), ExposureType.CLICK)
log(clickEvent)
bundle.putParcelable(KEY_TRACE_EVENT, clickEvent)
}
@ -928,31 +848,6 @@ object DirectUtils {
jumpActivity(context, bundle)
}
@JvmStatic
fun directToDownloadManager(
context: Context,
entrance: String = "",
bottomTab: String = "",
gameColumnId: String = "",
gameColumnName: String = "",
customPageId: String = "",
customPageName: String = "",
multiTabId: String = "",
multiTabName: String = ""
) {
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance)
bundle.putString(KEY_TO, DownloadManagerActivity.TAG)
bundle.putString(KEY_BOTTOM_TAB_NAME, bottomTab)
bundle.putString(KEY_GAME_COLUMN_ID, gameColumnId)
bundle.putString(KEY_GAME_COLUMN_NAME, gameColumnName)
bundle.putString(KEY_CUSTOM_PAGE_ID, customPageId)
bundle.putString(KEY_CUSTOM_PAGE_NAME, customPageName)
bundle.putString(KEY_MULTI_TAB_NAV_ID, multiTabId)
bundle.putString(KEY_MULTI_TAB_NAV_NAME, multiTabName)
jumpActivity(context, bundle)
}
@JvmStatic
fun directToDownloadManagerAndStartUpdate(
context: Context,
@ -973,7 +868,7 @@ object DirectUtils {
fun directToToolbox(context: Context, gameId: String, toolboxUrl: String, entrance: String = ENTRANCE_BROWSER) {
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance)
bundle.putString(KEY_TO, ToolBoxActivity::class.java.name)
bundle.putString(KEY_TO, ToolBoxBlockActivity::class.java.name)
bundle.putString(KEY_GAMEID, gameId)
bundle.putString(KEY_URL, toolboxUrl)
jumpActivity(context, bundle)
@ -991,14 +886,13 @@ object DirectUtils {
}
@JvmStatic
fun directToQuestionDetail(context: Context, id: String, entrance: String? = null, path: String? = null, sourceEntrance: String = "") {
fun directToQuestionDetail(context: Context, id: String, entrance: String? = null, path: String? = null) {
if (id.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_TO, NewQuestionDetailActivity::class.java.name)
bundle.putString(KEY_PATH, path)
bundle.putString(KEY_QUESTIONS_ID, id)
bundle.putString(KEY_SOURCE_ENTRANCE, sourceEntrance)
jumpActivity(context, bundle)
}
@ -1097,7 +991,12 @@ object DirectUtils {
@JvmStatic
fun directToGiftDetail(context: Context, giftId: String, entrance: String? = null) {
if (giftId.isEmpty()) return
context.startActivity(LibaoDetailActivity.getIntentById(context, giftId, entrance))
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_TO, LibaoDetailActivity::class.java.simpleName)
bundle.putString(EntranceConsts.KEY_ID, giftId)
HaloApp.put(LibaoEntity.TAG, null)
jumpActivity(context, bundle)
}
/**
@ -1114,7 +1013,21 @@ object DirectUtils {
*/
@JvmStatic
fun directToCommunity(context: Context, community: CommunityEntity?) {
// if (MainActivity::class.java.name != RunningUtils.getTopActivity(context)) {
// val intent = Intent(context, MainActivity::class.java)
// intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
// context.startActivity(intent)
//
// UserManager.getInstance().setCommunityData(community)
//
// // 这里换个线程操作是为了做一点延时
// AppExecutor.ioExecutor.execute {
// EventBus.getDefault().post(EBSkip(MainActivity.EB_SKIP_MAIN, MainWrapperFragment.INDEX_BBS))
// EventBus.getDefault().post(EBReuse(CommunityFragment.EB_RETRY_PAGE))
// }
// } else {
directForumDetail(context, community?.id)
// }
}
@JvmStatic
@ -1123,15 +1036,13 @@ object DirectUtils {
articleId: String?,
communityId: String?,
entrance: String?,
path: String?,
sourceEntrance: String = ""
path: String?
) {
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance ?: ENTRANCE_BROWSER)
bundle.putString(KEY_PATH, path)
bundle.putString(KEY_TO, ArticleDetailActivity::class.java.name)
bundle.putString(KEY_COMMUNITY_ARTICLE_ID, articleId)
bundle.putString(KEY_SOURCE_ENTRANCE, sourceEntrance)
bundle.putParcelable(KEY_COMMUNITY_DATA, CommunityEntity(id = communityId!!))
jumpActivity(context, bundle)
}
@ -1142,8 +1053,7 @@ object DirectUtils {
community: CommunityEntity?,
articleId: String?,
entrance: String?,
path: String?,
sourceEntrance: String = "",
path: String?
) {
if (articleId.isNullOrEmpty()) return
val bundle = Bundle()
@ -1151,7 +1061,6 @@ object DirectUtils {
bundle.putString(KEY_PATH, path)
bundle.putString(KEY_TO, ArticleDetailActivity::class.java.name)
bundle.putString(KEY_COMMUNITY_ARTICLE_ID, articleId)
bundle.putString(KEY_SOURCE_ENTRANCE, sourceEntrance)
bundle.putParcelable(KEY_COMMUNITY_DATA, community)
jumpActivity(context, bundle)
}
@ -1181,8 +1090,7 @@ object DirectUtils {
fun directToVideoDetail(
context: Context, videoId: String,
entrance: String? = null,
path: String? = "",
sourceEntrance: String = ""
path: String? = ""
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
val bundle = Bundle()
@ -1190,7 +1098,6 @@ object DirectUtils {
bundle.putString(KEY_TO, ForumVideoDetailActivity::class.java.name)
bundle.putString(KEY_VIDEO_ID, videoId);
bundle.putString(KEY_PATH, path)
bundle.putString(KEY_SOURCE_ENTRANCE, sourceEntrance)
jumpActivity(context, bundle)
} else {
DialogHelper.showVideoUnsupportedDialog(context)
@ -1216,8 +1123,7 @@ object DirectUtils {
paginationType: String = "",
fieldId: String = "",
sectionName: String = "",
isHomeVideo: Boolean = false,
sourceEntrance: String = ""
isHomeVideo: Boolean = false
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
val bundle = Bundle()
@ -1236,7 +1142,6 @@ object DirectUtils {
bundle.putString(KEY_FIELD_ID, fieldId)
bundle.putString(KEY_SECTION_NAME, sectionName)
bundle.putBoolean(KEY_IS_HOME_VIDEO, isHomeVideo)
SensorsBridge.trackAccessVideoStreaming(sourceEntrance)
jumpActivity(context, bundle)
} else {
DialogHelper.showVideoUnsupportedDialog(context)
@ -1252,10 +1157,9 @@ object DirectUtils {
gameId: String = "",
entrance: String? = null,
path: String? = "",
referer: String = "",
sourceEntrance: String = ""
referer: String = ""
) {
directToVideoDetail(context, videoId, entrance, path, sourceEntrance)
directToVideoDetail(context, videoId, entrance, path)
}
/**
@ -1556,61 +1460,85 @@ object DirectUtils {
}
/**
* 到首页-默认选中的 tab
* 到首页-首页 tab
*/
@JvmStatic
fun directToHomeDefaultTab(context: Context) {
fun directToHomeTab(context: Context) {
if (HaloApp.getInstance().isRunningForeground) {
val intent = Intent(context, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
context.startActivity(intent)
MainWrapperRepository.getInstance().sendReSelectDefaultTabEvent()
// 这里换个线程操作是为了做一点延时
runOnIoThread {
EventBus.getDefault().post(EBSkip(MainActivity.EB_SKIP_MAIN, MainWrapperFragment.INDEX_HOME))
}
} else {
jumpActivity(context, Bundle())
jumpActivity(context, Bundle().apply { putInt(KEY_POSITION, MainWrapperFragment.INDEX_HOME) })
}
}
/**
* 到首页-社区 tab
* @param position 社区子 tab 位置
* 到首页-论坛 tab
* @param position 论坛的子 tab 位置
*/
@JvmStatic
fun directToHomeCommunityTab(context: Context) {
val bundle = Bundle()
bundle.putString(KEY_TO, CommunityActivity::class.java.name)
jumpActivity(context, bundle)
fun directToForum(context: Context, position: Int = 0) {
if (HaloApp.getInstance().isRunningForeground) {
val intent = Intent(context, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
context.startActivity(intent)
// 这里换个线程操作是为了做一点延时
runOnIoThread {
EventBus.getDefault().post(EBSkip(MainActivity.EB_SKIP_MAIN, MainWrapperFragment.INDEX_BBS))
EventBus.getDefault().post(EBSkip(CommunityHomeFragment.EB_TAB, position))
}
} else {
jumpActivity(context, Bundle().apply {
putInt(KEY_POSITION, MainWrapperFragment.INDEX_BBS)
putInt(KEY_SUB_POSITION, position)
})
}
}
/**
* 到首页-视频 tab
*/
@JvmStatic
fun directToHomeVideoTab(context: Context) {
fun directToVideoTab(context: Context) {
if (HaloApp.getInstance().isRunningForeground) {
val intent = Intent(context, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
context.startActivity(intent)
} else {
jumpActivity(context, Bundle())
}
MainWrapperRepository.getInstance().sendSelectTabEvent(ViewPagerFragmentHelper.TYPE_VIDEO_STREAM)
// 这里换个线程操作是为了做一点延时
runOnIoThread {
EventBus.getDefault().post(EBSkip(MainActivity.EB_SKIP_MAIN, MainWrapperFragment.INDEX_VIDEO))
}
} else {
jumpActivity(context, Bundle().apply { putInt(KEY_POSITION, MainWrapperFragment.INDEX_VIDEO) })
}
}
/**
* 到首页-我的光环 tab
*/
fun directToHomeMyHaloTab(context: Context) {
@JvmStatic
fun directToPersonalTab(context: Context) {
if (HaloApp.getInstance().isRunningForeground) {
val intent = Intent(context, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
context.startActivity(intent)
} else {
jumpActivity(context, Bundle())
}
MainWrapperRepository.getInstance().sendSelectTabEvent(ViewPagerFragmentHelper.TYPE_MY_HALO)
// 这里换个线程操作是为了做一点延时
runOnIoThread {
EventBus.getDefault().post(EBSkip(MainActivity.EB_SKIP_MAIN, MainWrapperFragment.INDEX_PERSONAL))
}
} else {
jumpActivity(context, Bundle().apply { putInt(KEY_POSITION, MainWrapperFragment.INDEX_PERSONAL) })
}
}
/**
@ -1625,6 +1553,211 @@ object DirectUtils {
jumpActivityCompat(context, newBundle)
}
/**
* 跳转至商品详情
*/
@JvmStatic
fun directToCommodityDetail(context: Context, commodityId: String) {
var url: String = if (EnvHelper.isDevEnv) {
Constants.COMMODITY_DETAIL_ADDRESS_DEV
} else {
Constants.COMMODITY_DETAIL_ADDRESS
}
url = String.format(
Locale.CHINA,
"%s&shopid=%s&timestamp=%d",
url,
commodityId,
(Date().time / 1000 / 1000.toFloat()).roundToInt()
)
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至光能记录默认跳到光能记录第一个Tab
*/
@JvmStatic
fun directToEnergyRecord(context: Context) {
directToEnergyRecord(context, 0)
}
@JvmStatic
fun directToEnergyRecord(context: Context, position: Int) {
var url: String = if (EnvHelper.isDevEnv) {
Constants.ENERGY_RECORD_ADDRESS_DEV
} else {
Constants.ENERGY_RECORD_ADDRESS
}
url = String.format(
Locale.CHINA,
"%s&position=%s&timestamp=%d",
url,
position,
(Date().time / 1000 / 1000.toFloat()).roundToInt()
)
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至订单中心
*/
@JvmStatic
fun directToOrderCenter(context: Context) {
val url: String = if (EnvHelper.isDevEnv) {
Constants.ORDER_CENTER_ADDRESS_DEV
} else {
Constants.ORDER_CENTER_ADDRESS
}
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至订单详情
*/
@JvmStatic
fun directToOrderDetail(context: Context, orderId: String) {
var url: String = if (EnvHelper.isDevEnv) {
Constants.ORDER_DETAIL_ADDRESS_DEV
} else {
Constants.ORDER_DETAIL_ADDRESS
}
url = String.format(
Locale.CHINA,
"%s&order_id=%s&timestamp=%d",
url,
orderId,
(Date().time / 1000 / 1000.toFloat()).roundToInt()
)
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至邀请好友
*/
@JvmStatic
fun directToInviteFriends(context: Context) {
val url: String = if (EnvHelper.isDevEnv) {
Constants.INVITE_FRIENDS_ADDRESS_DEV
} else {
Constants.INVITE_FRIENDS_ADDRESS
}
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至等级页面
*/
@JvmStatic
fun directToLevelPage(context: Context) {
var url: String = if (isPublishEnv()) {
Constants.LEVEL_ADDRESS
} else {
Constants.LEVEL_ADDRESS_DEV
}
url = String.format(Locale.CHINA, "%s?timestamp=%d", url, (Date().time / 1000 / 1000.toFloat()).roundToInt())
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至兑换规则
*/
@JvmStatic
fun directToExchangeRulePage(context: Context) {
var url: String = if (isPublishEnv()) {
Constants.EXCHANGE_RULE_ADDRESS
} else {
Constants.EXCHANGE_RULE_ADDRESS_DEV
}
url = String.format(Locale.CHINA, "%s&timestamp=%d", url, (Date().time / 1000 / 1000.toFloat()).roundToInt())
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至光能规则
*/
@JvmStatic
fun directToEnergyRulePage(context: Context) {
var url: String = if (isPublishEnv()) {
Constants.ENERGY_RULE_ADDRESS
} else {
Constants.ENERGY_RULE_ADDRESS_DEV
}
url = String.format(Locale.CHINA, "%s&timestamp=%d", url, (Date().time / 1000 / 1000.toFloat()).roundToInt())
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至兑换商品
*/
@JvmStatic
fun directToExchangeCommodityPage(context: Context) {
var url: String = if (isPublishEnv()) {
Constants.EXCHANGE_COMMODITY_ADDRESS
} else {
Constants.EXCHANGE_COMMODITY_ADDRESS_DEV
}
url = String.format(Locale.CHINA, "%s&timestamp=%d", url, (Date().time / 1000 / 1000.toFloat()).roundToInt())
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至抽奖乐园
*/
@JvmStatic
fun directToLotteryParadisePage(context: Context) {
var url: String = if (isPublishEnv()) {
Constants.LOTTERY_PARADISE_ADDRESS
} else {
Constants.LOTTERY_PARADISE_ADDRESS_DEV
}
url = String.format(Locale.CHINA, "%s&timestamp=%d", url, (Date().time / 1000 / 1000.toFloat()).roundToInt())
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至我的奖品
*/
@JvmStatic
fun directToMyPrizePage(context: Context) {
var url: String = if (isPublishEnv()) {
Constants.MY_PRIZE_ADDRESS
} else {
Constants.MY_PRIZE_ADDRESS_DEV
}
url = String.format(Locale.CHINA, "%s&timestamp=%d", url, (Date().time / 1000 / 1000.toFloat()).roundToInt())
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至中奖订单详情
*/
@JvmStatic
fun directToWinOrderDetail(context: Context, orderId: String, activityId: String) {
var url: String = if (isPublishEnv()) {
Constants.WIN_ORDER_DETAIL_ADDRESS
} else {
Constants.WIN_ORDER_DETAIL_ADDRESS_DEV
}
url = String.format(
Locale.CHINA,
"%s&order_id=%s&activity_id=%s&timestamp=%d",
url,
orderId,
activityId,
(Date().time / 1000 / 1000.toFloat()).roundToInt()
)
directToFullScreenWebPage(context, url, true)
}
/**
* 跳转至地址信息
@ -1704,7 +1837,7 @@ object DirectUtils {
) {
if (collectionId.isEmpty()) return
val bundle = Bundle()
bundle.putString(KEY_TO, CustomCommonCollectionDetailActivity::class.java.name)
bundle.putString(KEY_TO, CommonCollectionDetailActivity::class.java.name)
bundle.putString(KEY_BLOCK_ID, blockId)
bundle.putString(KEY_BLOCK_NAME, blockName)
bundle.putString(KEY_ENTRANCE, entrance)
@ -1842,35 +1975,15 @@ object DirectUtils {
bbsId: String,
entrance: String,
sourceEntrance: String,
forumName: String,
bottomTab: String = "",
multiTabId: String = "",
multiTabName: String = "",
customPageId: String = "",
customPageName: String = "",
searchBoxPattern: String = ""
forumName: String
) {
context.startActivity(
ForumOrUserSearchActivity.getIntent(
context,
bbsId,
entrance,
sourceEntrance,
forumName,
bottomTab,
multiTabId,
multiTabName,
customPageId,
customPageName,
searchBoxPattern
)
)
context.startActivity(ForumOrUserSearchActivity.getIntent(context, bbsId, entrance, sourceEntrance, forumName))
}
@JvmStatic
fun directToVGameDownload(context: Context, entrance: String, switchToDownloadingTab: Boolean = false) {
fun directToVGameDownload(context: Context, switchToDownloadingTab: Boolean = false) {
val bundle = Bundle()
bundle.putString(KEY_ENTRANCE, entrance)
bundle.putString(KEY_ENTRANCE, ENTRANCE_BROWSER)
bundle.putString(KEY_TO, VDownloadManagerActivity::class.java.name)
bundle.putInt(KEY_POSITION, if (switchToDownloadingTab) 1 else 0)
jumpActivity(context, bundle)
@ -1938,27 +2051,9 @@ object DirectUtils {
fun directToQGameSearch(
context: Context,
hint: String,
sourceEntrance: String,
bottomTab: String = "",
multiTabId: String = "",
multiTabName: String = "",
customPageId: String = "",
customPageName: String = "",
searchBoxPattern: String = ""
sourceEntrance: String
) {
context.startActivity(
QGameSearchActivity.getIntent(
context,
hint,
sourceEntrance,
bottomTab,
multiTabId,
multiTabName,
customPageId,
customPageName,
searchBoxPattern
)
)
context.startActivity(QGameSearchActivity.getIntent(context, hint, sourceEntrance))
}
@SuppressLint("CheckResult")
@ -2051,62 +2146,4 @@ object DirectUtils {
context.startActivity(ServersCalendarManagementActivity.getIntent(context))
}
}
fun directToSearch(
context: Context,
searchType: String,
searchHint: String,
entrance: String,
sourceEntrance: String,
bottomTab: String = "",
multiTabId: String = "",
multiTabName: String = "",
customPageId: String = "",
customPageName: String = "",
searchBoxPattern: String = ""
) {
when (searchType) {
BottomTab.SearchStyle.TYPE_HALO_GAME -> context.startActivity(
SearchActivity.getIntent(
context,
false,
searchHint,
entrance,
sourceEntrance,
bottomTab,
multiTabId,
multiTabName,
customPageId,
customPageName,
searchBoxPattern
)
)
BottomTab.SearchStyle.TYPE_QQ_MINI_GAME -> directToQGameSearch(
context,
"请输入小游戏关键词",
sourceEntrance,
bottomTab,
multiTabId,
multiTabName,
customPageId,
customPageName,
searchBoxPattern
)
BottomTab.SearchStyle.TYPE_BBS -> directToForumOrUserSearch(
context,
"",
entrance,
sourceEntrance,
"",
bottomTab,
multiTabId,
multiTabName,
customPageId,
customPageName,
searchBoxPattern
)
}
}
}

View File

@ -6,7 +6,6 @@ import android.text.TextUtils
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.collection.ArrayMap
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import com.gh.common.chain.*
import com.gh.common.constant.Config
@ -46,6 +45,7 @@ import com.gh.vspace.VHelper
import com.lightgame.download.DownloadConfig
import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus
import com.lightgame.download.FileUtils
import com.lightgame.utils.Utils
import java.io.File
import java.util.concurrent.LinkedBlockingQueue
@ -199,7 +199,7 @@ object DownloadItemUtils {
holder.gameDownloadTips?.visibility = View.GONE
updateNormalItem(context, holder, gameEntity, briefStyle, isShowRecommendStar)
} else {
holder.multiVersionDownloadTv?.isVisible = !SPUtils.getBoolean(Constants.SP_TEENAGER_MODE)
holder.multiVersionDownloadTv?.visibility = View.VISIBLE
updatePluginItem(context, holder, gameEntity, briefStyle, isShowRecommendStar)
}
updateDownloadButton(
@ -219,7 +219,7 @@ object DownloadItemUtils {
pluginLocation: PluginLocation? = PluginLocation.only_game
) {
// 控制是否显示下载按钮
downloadBtn.goneIf(context.getString(R.string.app_name) == gameEntity.name)
downloadBtn.goneIf(!Config.isShowDownload(gameEntity.id) || context.getString(R.string.app_name) == gameEntity.name)
// 青少年模式或者需要特殊处理显示查看
if (SPUtils.getBoolean(Constants.SP_TEENAGER_MODE) || gameEntity.isSpecialDownload()) {
downloadBtn.text = "查看"
@ -443,7 +443,6 @@ object DownloadItemUtils {
briefStyle: String?,
isShowRecommendStar: Boolean = false
) {
updateItemViewStatus(holder, briefStyle, gameEntity.columnRecommend, isShowRecommendStar)
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
if (downloadEntity != null) {
if (downloadEntity.isSimulatorGame()) {
@ -458,6 +457,7 @@ object DownloadItemUtils {
return
}
}
updateItemViewStatus(holder, briefStyle, gameEntity.columnRecommend, isShowRecommendStar)
}
// 更新插件的条目有多个apk包
@ -624,10 +624,9 @@ object DownloadItemUtils {
position: Int,
adapter: RecyclerView.Adapter<out RecyclerView.ViewHolder?>?,
entrance: String,
location: String,
sourceEntrance: String = "其他"
location: String
) {
setOnClickListener(context, downloadBtn, gameEntity, position, adapter, entrance, sourceEntrance, location, null)
setOnClickListener(context, downloadBtn, gameEntity, position, adapter, entrance, location, null)
}
@JvmStatic
@ -638,11 +637,10 @@ object DownloadItemUtils {
position: Int,
adapter: RecyclerView.Adapter<out RecyclerView.ViewHolder?>?,
entrance: String,
sourceEntrance: String = "其他",
location: String,
traceEvent: ExposureEvent?,
traceEvent: ExposureEvent?
) {
setOnClickListener(context, downloadBtn, gameEntity, position, adapter, entrance, sourceEntrance, location, traceEvent, null)
setOnClickListener(context, downloadBtn, gameEntity, position, adapter, entrance, location, traceEvent, null)
}
/**
@ -656,10 +654,9 @@ object DownloadItemUtils {
position: Int,
adapter: RecyclerView.Adapter<out RecyclerView.ViewHolder?>?,
entrance: String,
sourceEntrance: String = "其他",
location: String,
traceEvent: ExposureEvent?,
clickCallback: EmptyCallback?,
clickCallback: EmptyCallback?
) {
setOnClickListener(
context,
@ -668,7 +665,6 @@ object DownloadItemUtils {
position,
adapter,
entrance,
sourceEntrance,
location,
traceEvent,
clickCallback,
@ -688,7 +684,6 @@ object DownloadItemUtils {
position: Int,
adapter: RecyclerView.Adapter<out RecyclerView.ViewHolder?>?,
entrance: String,
sourceEntrance: String = "其他",
location: String,
traceEvent: ExposureEvent?,
clickCallback: EmptyCallback?,
@ -776,33 +771,31 @@ object DownloadItemUtils {
return
}
if (gameEntity.isReservable) {
downloadBtn.setOnClickListener {
if (!ReservationRepository.thisGameHasBeenReserved(gameEntity.id)) {
if (!ReservationRepository.thisGameHasBeenReserved(gameEntity.id)) {
downloadBtn.setOnClickListener {
SensorsBridge.trackEvent(
"AppointmentGame",
"game_name",
gameEntity.name ?: "",
"game_id",
gameEntity.id,
"game_type",
gameEntity.categoryChinese,
"source_entrance",
sourceEntrance
gameEntity.id
)
allStateClickCallback?.onCallback()
CheckLoginUtils.checkLogin(context, entrance) {
clickCallback?.onCallback()
ReservationHelper.reserve(
context,
gameEntity,
sourceEntrance
gameEntity.id,
gameEntity.name ?: ""
) {
LogUtils.logReservation(gameEntity, traceEvent)
adapter?.notifyItemChanged(position)
refreshCallback?.onCallback()
}
}
} else {
}
} else {
downloadBtn.setOnClickListener {
allStateClickCallback?.onCallback()
clickCallback?.onCallback()
if ("download" == gameEntity.reserveStatus) {
@ -910,6 +903,7 @@ object DownloadItemUtils {
DownloadChainBuilder().apply {
addHandler(GamePermissionHandler())
addHandler(CheckStoragePermissionHandler())
addHandler(CertificationHandler())
addHandler(VersionNumberHandler())
}
.setProcessEndCallback { _, _ ->
@ -951,6 +945,7 @@ object DownloadItemUtils {
addHandler(BrowserInstallHandler())
addHandler(PackageCheckHandler())
addHandler(DownloadDialogHelperHandler())
addHandler(CertificationHandler())
addHandler(OverseaDownloadHandler())
addHandler(LandPageAddressHandler())
addHandler(CheckDownloadHandler())
@ -969,6 +964,7 @@ object DownloadItemUtils {
addHandler(BrowserInstallHandler())
addHandler(PackageCheckHandler())
addHandler(DownloadDialogHelperHandler())
addHandler(CertificationHandler())
addHandler(VersionNumberHandler())
addHandler(LandPageAddressHandler())
addHandler(OverseaDownloadHandler())
@ -986,6 +982,7 @@ object DownloadItemUtils {
addHandler(GamePermissionHandler())
addHandler(PackageCheckHandler())
addHandler(DownloadDialogHelperHandler())
addHandler(CertificationHandler())
addHandler(VersionNumberHandler())
addHandler(LandPageAddressHandler())
addHandler(OverseaDownloadHandler())
@ -1004,6 +1001,7 @@ object DownloadItemUtils {
} else {
DownloadChainBuilder().apply {
addHandler(DownloadDialogHelperHandler())
addHandler(CertificationHandler())
addHandler(CheckDownloadHandler())
}
.setProcessEndCallback { _, isSubscribe ->
@ -1059,7 +1057,7 @@ object DownloadItemUtils {
NewSimulatorGameManager.showUpdateNewsSimulator(context, gameEntity, null)
return
}
val downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(gameEntity.getApk().firstOrNull()?.url)
val downloadEntity = SimulatorGameManager.findDownloadEntityByUrl(gameEntity.getApk()[0].url)
if (downloadEntity != null) {
val file = File(downloadEntity.path)
if (!file.exists()) {
@ -1153,7 +1151,7 @@ object DownloadItemUtils {
) {
if (gameEntity.getApk().isEmpty()) return
val msg = FileUtils.isCanDownload(context, gameEntity.getApk().firstOrNull()?.size ?: "")
val msg = FileUtils.isCanDownload(context, gameEntity.getApk()[0].size ?: "")
if (TextUtils.isEmpty(msg)) {
DownloadManager.createDownload(
context,
@ -1191,7 +1189,7 @@ object DownloadItemUtils {
isSubscribe: Boolean,
traceEvent: ExposureEvent?
) {
val msg = FileUtils.isCanDownload(context, gameEntity.getApk().firstOrNull()?.size ?: "")
val msg = FileUtils.isCanDownload(context, gameEntity.getApk()[0].size ?: "")
if (TextUtils.isEmpty(msg)) {
DownloadManager.createDownload(context, gameEntity, false, entrance, location, isSubscribe, traceEvent)
ToastUtils.toast(gameEntity.name + "已加入下载队列")
@ -1218,7 +1216,7 @@ object DownloadItemUtils {
adapter: RecyclerView.Adapter<out RecyclerView.ViewHolder?>?,
refreshCallback: EmptyCallback?
) {
val apkEntity = gameEntity.getApk().firstOrNull()
val apkEntity = gameEntity.getApk()[0]
val downloadEntity = DownloadManager.getInstance().getDownloadEntitySnapshot(gameEntity)
if (downloadEntity != null) {
val path = downloadEntity.path
@ -1226,7 +1224,7 @@ object DownloadItemUtils {
FileUtils.isEmptyFile(path) -> {
Utils.toast(context, R.string.install_failure_hint)
DownloadManager.getInstance().cancel(downloadEntity.url)
gameEntity.getEntryMap().remove(apkEntity?.getPlatform())
gameEntity.getEntryMap().remove(apkEntity.getPlatform())
adapter?.notifyItemChanged(position)
refreshCallback?.onCallback()
}

View File

@ -18,13 +18,12 @@ import com.gh.gamecenter.common.entity.SimpleGameEntity
import com.gh.gamecenter.common.entity.SuggestType
import com.gh.gamecenter.common.eventbus.EBShowDialog
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.utils.NewFlatLogUtils
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.core.utils.MtaHelper
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.common.utils.NewFlatLogUtils
import com.gh.gamecenter.eventbus.EBDownloadStatus
import com.gh.gamecenter.feature.entity.CustomPageTrackData
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.SimulatorEntity
import com.gh.gamecenter.feature.utils.PlatformUtils
@ -32,10 +31,7 @@ import com.gh.gamecenter.help.HelpAndFeedbackBridge
import com.gh.gamecenter.pkg.PkgHelper
import com.gh.vspace.VHelper
import com.halo.assistant.HaloApp
import com.lightgame.download.DataWatcher
import com.lightgame.download.DownloadConfig
import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus
import com.lightgame.download.*
import com.lightgame.utils.AppManager
import com.lightgame.utils.Utils
import org.greenrobot.eventbus.EventBus
@ -194,10 +190,9 @@ object DownloadObserver {
confirmClickCallback = {
currentActivity.startActivity(
ShellActivity.getIntent(
currentActivity,
ShellActivity.Type.REAL_NAME_INFO,
)
)
currentActivity,
ShellActivity.Type.REAL_NAME_INFO,
))
}
)
} else {
@ -333,13 +328,8 @@ object DownloadObserver {
simulator = newSimulator ?: simulator
}
SimulatorDownloadManager.getInstance().showDownloadDialog(
currentActivity,
simulator,
SimulatorDownloadManager.SimulatorLocation.LAUNCH,
downloadEntity.gameId,
gameName,
downloadEntity.categoryChinese,
null
currentActivity, simulator,
SimulatorDownloadManager.SimulatorLocation.LAUNCH, downloadEntity.gameId, gameName, downloadEntity.categoryChinese, null
)
SimulatorGameManager.recordDownloadSimulatorGame(downloadEntity.gameId, simulator.type)
SimulatorGameManager.postPlayedGame(downloadEntity.gameId, downloadEntity.packageName)
@ -354,8 +344,7 @@ object DownloadObserver {
} else {
if (PackageUtils.isCanLaunchSetup(mApplication, downloadEntity.path)
|| downloadType == Constants.VGAME
|| downloadType == Constants.DUAL_DOWNLOAD_VGAME
) {
|| downloadType == Constants.DUAL_DOWNLOAD_VGAME) {
downloadEntity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION] = "YES"
tryWithDefaultCatch {
NewFlatLogUtils.logGameInstall(
@ -487,20 +476,12 @@ object DownloadObserver {
)
if (downloadEntity.asVGame()) {
val customTrackDataJson = downloadEntity.customPageTrackDataJson
val kvs = if (customTrackDataJson.isNullOrBlank()) {
arrayOf<String>()
} else {
GsonUtils.fromJson(customTrackDataJson, CustomPageTrackData::class.java).toKV()
}
SensorsBridge.trackEventWithExposureSource(
"HaloFunGameDownloadDone",
exposureEvent?.source,
"game_name", downloadEntity.name,
"game_id", downloadEntity.gameId,
"game_type", downloadEntity.categoryChinese,
"game_schema_type", if (downloadEntity.getMetaExtra(VHelper.KEY_BIT) == "32") "32位" else "64位",
*kvs
"game_schema_type", if (downloadEntity.getMetaExtra(VHelper.KEY_BIT) == "32") "32位" else "64位"
)
} else if (downloadEntity.gameId == Constants.HALO_FUN_GAME_ID) {
SensorsBridge.trackEvent(
@ -508,36 +489,33 @@ object DownloadObserver {
"space_schema_type",
if (downloadEntity.packageName == VHelper.VSPACE_32BIT_PACKAGENAME) "32位" else "64位"
)
} else if(downloadEntity.gameId == Constants.HALO_FUN_NEW_32_GAME_ID) {
SensorsBridge.trackEvent(
"HaloFunDownloadDone",
"space_schema_type",
"32位(新)"
)
}
if (downloadEntity.gameId != Constants.GHZS_GAME_ID
&& downloadEntity.getMetaExtra(Constants.EXTRA_DOWNLOAD_TYPE) != Constants.SIMULATOR_DOWNLOAD
&& downloadEntity.gameId != Constants.HALO_FUN_GAME_ID
) {
val trackJson = downloadEntity.customPageTrackDataJson
val kvs = if (!trackJson.isNullOrBlank()) {
GsonUtils.fromJson(trackJson, CustomPageTrackData::class.java).toKV()
} else {
arrayOf()
}
SensorsBridge.trackEventWithExposureSource(
"DownloadProcessFinish",
exposureEvent?.source,
"game_id", downloadEntity.gameId,
"game_name", downloadEntity.meta[Constants.GAME_NAME] ?: "",
"game_type", downloadEntity.meta[Constants.GAME_CATEGORY_IN_CHINESE] ?: "",
"game_label", downloadEntity.tags.joinToString(","),
"game_schema_type", if (downloadEntity.getMetaExtra(VHelper.KEY_BIT) == "32") "32位" else "64位",
"page_name", getCurrentPageEntity().pageName,
"page_id", getCurrentPageEntity().pageId,
"page_business_id", getCurrentPageEntity().pageBusinessId,
"last_page_name", getLastPageEntity().pageName,
"last_page_id", getLastPageEntity().pageId,
"last_page_business_id", getLastPageEntity().pageBusinessId,
"download_status", downloadEntity.meta[Constants.DOWNLOAD_STATUS_IN_CHINESE] ?: "",
"download_type", if (downloadEntity.asVGame()) "畅玩下载" else "本地下载",
*kvs
)
&& downloadEntity.gameId != Constants.HALO_FUN_NEW_32_GAME_ID) {
SensorsBridge.trackEventWithExposureSource(
"DownloadProcessFinish",
exposureEvent?.source,
"game_id", downloadEntity.gameId,
"game_name", downloadEntity.meta[Constants.GAME_NAME] ?: "",
"game_type", downloadEntity.meta[Constants.GAME_CATEGORY_IN_CHINESE] ?: "",
"game_schema_type", if (downloadEntity.getMetaExtra(VHelper.KEY_BIT) == "32") "32位" else "64位",
"page_name", getCurrentPageEntity().pageName,
"page_id", getCurrentPageEntity().pageId,
"page_business_id", getCurrentPageEntity().pageBusinessId,
"last_page_name", getLastPageEntity().pageName,
"last_page_id", getLastPageEntity().pageId,
"last_page_business_id", getLastPageEntity().pageBusinessId,
"download_type", if (downloadEntity.asVGame()) "畅玩下载" else "本地下载",
)
}
DataCollectionUtils.uploadDownload(mApplication, downloadEntity, "完成")

View File

@ -13,14 +13,11 @@ import com.gh.gamecenter.VerifyPhoneActivity
import com.gh.gamecenter.WebActivity
import com.gh.gamecenter.common.avoidcallback.AvoidOnResultManager
import com.gh.gamecenter.common.avoidcallback.Callback
import com.gh.gamecenter.common.callback.CancelListener
import com.gh.gamecenter.common.callback.ConfirmListener
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.entity.ErrorEntity
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.feature.entity.GameEntity
import com.halo.assistant.fragment.user.UserInfoEditFragment
import com.halo.assistant.fragment.user.VerifyPhoneFragment
import com.lightgame.utils.AppManager
@ -42,12 +39,8 @@ object ErrorHelper {
context: Context,
errorString: String?,
showHighPriorityHint: Boolean = false,
sourceEntrance: String = "",
articleType: String = "",
verificationType: String = "内容实名",
gameEntity: GameEntity? = null,
realNameConfirmListener: ConfirmListener? = null,
customizedHandler: (code: Int) -> Boolean,
customizedHandler: (code: Int) -> Boolean
) {
val errorEntity = errorString?.toObject<ErrorEntity>()
@ -65,17 +58,7 @@ object ErrorHelper {
return
}
handleError(
context,
showHighPriorityHint,
errorEntity,
"",
sourceEntrance,
articleType,
verificationType,
gameEntity,
realNameConfirmListener,
)
handleError(context, showHighPriorityHint, errorEntity, realNameConfirmListener)
}
/**
@ -87,12 +70,8 @@ object ErrorHelper {
context: Context,
errorString: String?,
showHighPriorityHint: Boolean = false,
entrance: String = "",
sourceEntrance: String = "",
articleType: String = "",
verificationType: String = "内容实名",
gameEntity: GameEntity? = null,
realNameConfirmListener: ConfirmListener? = null
realNameConfirmListener: ConfirmListener? = null,
entrance: String = ""
) {
val errorEntity = errorString?.toObject<ErrorEntity>()
@ -106,17 +85,7 @@ object ErrorHelper {
return
}
handleError(
context,
showHighPriorityHint,
errorEntity,
entrance,
sourceEntrance,
articleType,
verificationType,
gameEntity,
realNameConfirmListener
)
handleError(context, showHighPriorityHint, errorEntity, realNameConfirmListener, entrance)
}
/***
@ -140,12 +109,8 @@ object ErrorHelper {
context: Context,
showHighPriorityHint: Boolean = false,
errorEntity: ErrorEntity,
entrance: String = "",
sourceEntrance: String = "",
articleType: String = "",
verificationType: String = "内容实名",
gameEntity: GameEntity? = null,
realNameConfirmListener: ConfirmListener? = null,
entrance: String = ""
) {
when (errorEntity.code) {
403050,
@ -166,7 +131,6 @@ object ErrorHelper {
403057,
403068 -> handleErrorWithCommentBannedDialog(context, errorEntity)
403200,
403201,
403202 -> handleErrorWithGameCollectionBannedDialog(context, errorEntity)
@ -213,17 +177,9 @@ object ErrorHelper {
// 多设备登录同一帐号,不需要这里处理
}
403209 -> handleRealNameError(
context,
errorEntity,
sourceEntrance,
articleType,
verificationType,
gameEntity,
realNameConfirmListener,
)
403209 -> handleRealNameError(context, errorEntity, realNameConfirmListener)
403210 -> handleVerifyPhoneError(context, errorEntity, entrance, articleType, realNameConfirmListener)
403210 -> handleVerifyPhoneError(context, errorEntity, realNameConfirmListener, entrance)
// 禁言(发布内容)
403402 -> Utils.toast(context, "您的账号存在违规,不允许发布内容")
@ -251,21 +207,8 @@ object ErrorHelper {
private fun handleRealNameError(
context: Context,
errorEntity: ErrorEntity,
sourceEntrance: String = "",
articleType: String = "",
verificationType: String = "内容实名",
gameEntity: GameEntity? = null,
realNameConfirmListener: ConfirmListener?,
realNameConfirmListener: ConfirmListener?
) {
SensorsBridge.trackVerificationDialogShow(
gameId = gameEntity?.id ?: "",
gameName = gameEntity?.name ?: "",
gameType = gameEntity?.categoryChinese ?:"",
articleType = articleType,
verificationType = verificationType
)
DialogHelper.showDialog(
context,
"实名提醒",
@ -300,25 +243,23 @@ object ErrorHelper {
}
},
confirmClickCallback = {
SensorsBridge.trackVerificationPopupClick("前往实名认证")
val currentActivity = AppManager.getInstance().currentActivity() ?: return@showDialog
val intent = ShellActivity.getIntent(context, ShellActivity.Type.REAL_NAME_INFO)
.putExtra(EntranceConsts.KEY_SOURCE_ENTRANCE, sourceEntrance)
AvoidOnResultManager.getInstance(currentActivity as AppCompatActivity)
.startForResult(intent, object : Callback {
override fun onActivityResult(resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK && data != null) {
val isAuthSuccess =
data.getBooleanExtra(UserInfoEditFragment.AUTH_SUCCESS, false)
if (isAuthSuccess) {
realNameConfirmListener?.onConfirm()
.startForResult(
ShellActivity.getIntent(
context,
ShellActivity.Type.REAL_NAME_INFO,
), object : Callback {
override fun onActivityResult(resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK && data != null) {
val isAuthSuccess =
data.getBooleanExtra(UserInfoEditFragment.AUTH_SUCCESS, false)
if (isAuthSuccess) {
realNameConfirmListener?.onConfirm()
}
}
}
}
})
},
cancelClickCallback = {
SensorsBridge.trackVerificationPopupClick("以后再说")
})
}
)
}
@ -326,15 +267,9 @@ object ErrorHelper {
private fun handleVerifyPhoneError(
context: Context,
errorEntity: ErrorEntity,
entrance: String,
articleType: String,
realNameConfirmListener: ConfirmListener?,
entrance: String
) {
SensorsBridge.trackMobileNumberVerificationDialog(
articleType = articleType
)
DialogHelper.showDialog(
context,
"手机号验证",
@ -384,12 +319,10 @@ object ErrorHelper {
}
}
})
SensorsBridge.trackMobileNumberVerificationPopupClick(buttonName = "前往手机号验证")
NewFlatLogUtils.logPhoneNumberVerifyDialogClick(entrance, "前往手机号验证")
NewFlatLogUtils.logPhoneNumberVerifyDialogShow("手机号验证弹窗-前往验证")
},
cancelClickCallback = {
SensorsBridge.trackMobileNumberVerificationPopupClick(buttonName = "以后再说")
NewFlatLogUtils.logPhoneNumberVerifyDialogClick(entrance, "以后再说")
}
)

View File

@ -6,6 +6,7 @@ import android.text.TextUtils
import androidx.appcompat.app.AppCompatActivity
import com.gh.common.DefaultJsApi
import com.gh.common.constant.Config
import com.gh.common.dialog.CertificationDialog
import com.gh.common.exposure.ExposureManager
import com.gh.common.history.HistoryHelper
import com.gh.common.repository.ReservationRepository
@ -41,6 +42,7 @@ import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.teenagermode.TeenagerModeActivity
import com.gh.vspace.VHelper
import com.lightgame.download.DownloadEntity
import com.lightgame.download.FileUtils
import com.lightgame.utils.Utils
import java.io.File
@ -161,10 +163,12 @@ object GameActivityDownloadHelper {
) {
if (!ReservationRepository.thisGameHasBeenReserved(gameEntity.id)) {
CheckLoginUtils.checkLogin(context, entrance) {
ReservationHelper.reserve(context, gameEntity) {
LogUtils.logReservation(gameEntity, traceEvent)
clear()
}
ReservationHelper.reserve(context, gameEntity.id, gameEntity.name ?: "", object : EmptyCallback {
override fun onCallback() {
LogUtils.logReservation(gameEntity, traceEvent)
clear()
}
})
}
} else {
ToastUtils.toast("游戏已成功预约")
@ -260,14 +264,10 @@ object GameActivityDownloadHelper {
traceEvent: ExposureEvent
) {
GamePermissionDialogFragment.show((context as AppCompatActivity), gameEntity, gameEntity.info) {
DialogUtils.checkDownload(
context,
apk.size,
gameEntity.id,
gameEntity.name,
gameEntity.categoryChinese
) { isSubscribe: Boolean ->
download(context, gameEntity, apk, false, isSubscribe, entrance, location, traceEvent)
CertificationDialog.showCertificationDialog(context, gameEntity) {
DialogUtils.checkDownload(context, apk.size, gameEntity.id, gameEntity.name, gameEntity.categoryChinese) { isSubscribe: Boolean ->
download(context, gameEntity, apk, false, isSubscribe, entrance, location, traceEvent)
}
}
}
DataLogUtils.uploadGameLog(context, gameEntity.id, gameEntity.name, entrance)
@ -282,16 +282,18 @@ object GameActivityDownloadHelper {
location: String,
traceEvent: ExposureEvent
) {
VHelper.validateVSpaceBeforeAction(context, gameEntity) {
VHelper.validateVSpaceBeforeAction(context,gameEntity.getUniquePackageName(), gameEntity) {
GamePermissionDialogFragment.show((context as AppCompatActivity), gameEntity, gameEntity.info) {
DialogUtils.checkDownload(
context,
apk.size,
gameEntity.id,
gameEntity.name,
gameEntity.categoryChinese
) { isSubscribe: Boolean ->
download(context, gameEntity, apk, true, isSubscribe, entrance, location, traceEvent)
CertificationDialog.showCertificationDialog(context, gameEntity) {
DialogUtils.checkDownload(
context,
apk.size,
gameEntity.id,
gameEntity.name,
gameEntity.categoryChinese
) { isSubscribe: Boolean ->
download(context, gameEntity, apk, true, isSubscribe, entrance, location, traceEvent)
}
}
}
}
@ -309,14 +311,10 @@ object GameActivityDownloadHelper {
if (gameEntity.pluggableCollection != null) {
DownloadDialog.showDownloadDialog(context, gameEntity, traceEvent, entrance, location)
} else {
DialogUtils.checkDownload(
context,
apk.size,
gameEntity.id,
gameEntity.name,
gameEntity.categoryChinese
) { isSubscribe: Boolean ->
plugin(context, gameEntity, apk, entrance, location, isSubscribe, traceEvent)
CertificationDialog.showCertificationDialog(context, gameEntity) {
DialogUtils.checkDownload(context, apk.size, gameEntity.id, gameEntity.name, gameEntity.categoryChinese) { isSubscribe: Boolean ->
plugin(context, gameEntity, apk, entrance, location, isSubscribe, traceEvent)
}
}
}
}
@ -384,7 +382,7 @@ object GameActivityDownloadHelper {
return
}
val simulatorDownloadEntity =
SimulatorGameManager.findDownloadEntityByUrl(gameEntity.getApk().firstOrNull()?.url)
SimulatorGameManager.findDownloadEntityByUrl(gameEntity.getApk()[0].url)
if (simulatorDownloadEntity != null) {
val file = File(simulatorDownloadEntity.path)
if (!file.exists()) {
@ -431,7 +429,7 @@ object GameActivityDownloadHelper {
return when {
gameEntity.getApk().isEmpty() -> null
gameEntity.getApk().size == 1 -> gameEntity.getApk().firstOrNull()
gameEntity.getApk().size == 1 -> gameEntity.getApk()[0]
// 找出对应平台版本Apk且移除掉其他平台版本Apk
isRemoveOther -> {

View File

@ -1,16 +1,21 @@
package com.gh.common.util
import android.annotation.SuppressLint
import android.content.Context
import android.text.TextUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.common.utils.doOnMainProcessOnly
import com.gh.gamecenter.common.utils.toJson
import com.gh.gamecenter.common.utils.toObject
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.entity.SubjectEntity
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import io.reactivex.schedulers.Schedulers
import okhttp3.ResponseBody
/**
* 补充游戏库管理类
@ -21,10 +26,15 @@ object GameSubstituteRepositoryHelper {
private const val KEY_GAME_REPOSITORY = "game_substitute_repository"
private var mApi = RetrofitManager.getInstance().api
private var mHistoricInstalledGameIdSet = hashSetOf<String>() // 历史已安装过的游戏 ID 列表
private var mApplicationContext = HaloApp.getInstance().application
private val mGameSubSp by lazy { mApplicationContext.getSharedPreferences(SP_GAME_SUB, Context.MODE_PRIVATE) }
private var mGameCollectionList: List<SubjectEntity>? = null // 游戏补充库
private var mGameCollectionList: List<SubjectEntity> = arrayListOf() // 游戏补充库
init {
loadSavedRepository()
}
/**
* 获取游戏补充库
@ -33,26 +43,48 @@ object GameSubstituteRepositoryHelper {
fun updateGameSubstituteRepository() {
mApi.reserveColumns
.subscribeOn(Schedulers.io())
.subscribe(object : Response<ResponseBody>() {
override fun onResponse(response: ResponseBody?) {
.subscribe(object : Response<List<SubjectEntity>>() {
override fun onResponse(response: List<SubjectEntity>?) {
super.onResponse(response)
if (response != null) {
updateGameRepository(response)
}
updateGameRepository(response)
}
})
}
private fun updateGameRepository(response: ResponseBody) {
val responseContent = response.string()
SPUtils.setString(mGameSubSp, KEY_GAME_REPOSITORY, responseContent)
if (mGameCollectionList?.isEmpty() == true) {
mGameCollectionList = responseContent.toObject()
/**
* 联网获取历史已安装过的游戏 ID 列表
* 包括根据用户 ID 获取的已玩游戏 ID 列表,以及根据 gid 获取的已下载游戏 ID 列表
*/
@JvmStatic
@SuppressLint("CheckResult")
fun updateHistoricInstalledGameSet() {
mApplicationContext.doOnMainProcessOnly {
val single = if (UserManager.getInstance().isLoggedIn) {
mApi.getIdListOfPlayedGames(UserManager.getInstance().userId, Utils.getTime(mApplicationContext))
} else {
mApi.getIdListOfDownloadedGames(HaloApp.getInstance().gid, Utils.getTime(mApplicationContext))
}
single.subscribeOn(Schedulers.io()).subscribe(object : BiResponse<List<String>>() {
override fun onSuccess(data: List<String>) {
mHistoricInstalledGameIdSet = data.toHashSet()
}
})
}
}
private fun loadSavedRepository() {
mGameCollectionList = SPUtils.getString(mGameSubSp, KEY_GAME_REPOSITORY).toObject() ?: arrayListOf()
}
private fun updateGameRepository(subjects: List<SubjectEntity>?) {
if (subjects == null) return
SPUtils.setString(mGameSubSp, KEY_GAME_REPOSITORY, subjects.toJson())
mGameCollectionList = subjects
}
/**
* 从补充游戏库相应的专题中取出一个与其它游戏都不相同的游戏,为空时即为游戏用完或不存在该相应专题
* @param collectionId 补充游戏库相应专题 ID
@ -60,7 +92,7 @@ object GameSubstituteRepositoryHelper {
*/
private fun getValidGame(collectionId: String?, gameIdList: HashSet<String>): GameEntity? {
collectionId?.let {
val collection = mGameCollectionList?.find { it.id == collectionId }
val collection = mGameCollectionList.find { it.id == collectionId }
collection?.let {
val game = collection.data?.find { game -> isThisGameValid(game, gameIdList) }
game?.let {
@ -81,12 +113,10 @@ object GameSubstituteRepositoryHelper {
* @param relatedCollectionId 关联的替换合集 ID
*/
fun replaceGames(
gameList: MutableList<GameEntity>?,
gameList: MutableList<GameEntity>,
displayingGameIdSet: HashSet<String>,
relatedCollectionId: String,
) {
if (gameList == null) return
// 需要被替换的游戏 position 列表
val positionOfGameToBeReplacedList = arrayListOf<Int>()
@ -101,13 +131,21 @@ object GameSubstituteRepositoryHelper {
// 这个 position 的游戏是否需要被替换
var thisPositionNeedToBeReplaced = false
// 从 游戏ID 判断当前游戏是否需要被替换
if (mHistoricInstalledGameIdSet.contains(game.id)) {
positionOfGameToBeReplacedList.add(index)
thisPositionNeedToBeReplaced = true
}
// 检查是否已安装该游戏里同包名的 APK
for (apk in game.getApk()) {
if (PackageHelper.validLocalPackageNameSet.contains(apk.packageName)) {
// 将该位置的游戏标记为需要替换
positionOfGameToBeReplacedList.add(index)
thisPositionNeedToBeReplaced = true
break
if (!thisPositionNeedToBeReplaced) {
for (apk in game.getApk()) {
if (PackageHelper.validLocalPackageNameSet.contains(apk.packageName)) {
// 将该位置的游戏标记为需要替换
positionOfGameToBeReplacedList.add(index)
thisPositionNeedToBeReplaced = true
break
}
}
}
@ -130,14 +168,7 @@ object GameSubstituteRepositoryHelper {
}
}
// 若待替换的位置列表不为空,尝试执行替换
if (positionOfGameToBeReplacedList.isNotEmpty()) {
if (mGameCollectionList == null) {
mGameCollectionList = SPUtils.getString(mGameSubSp, KEY_GAME_REPOSITORY).toObject() ?: arrayListOf()
}
if (mGameCollectionList.isNullOrEmpty()) return
for (position in positionOfGameToBeReplacedList) {
val validGame = getValidGame(relatedCollectionId, displayingGameIdSet)
validGame?.let {
@ -157,6 +188,9 @@ object GameSubstituteRepositoryHelper {
game: GameEntity,
gameIdList: HashSet<String>
): Boolean {
// 该游戏是否在历史已安装列表中
if (mHistoricInstalledGameIdSet.contains(game.id)) return false
// 该游戏是否与专题里已包含的游戏存在关联关系
for (relatedId in game.relatedGameIds!!) {
if (gameIdList.contains(relatedId)) {

View File

@ -2,15 +2,20 @@ package com.gh.common.util;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import androidx.core.content.ContextCompat;
import com.gh.gamecenter.common.utils.ExtensionsKt;
import com.gh.gamecenter.core.AppExecutor;
import com.gh.gamecenter.common.view.DrawableView;
import com.gh.gamecenter.R;
import com.gh.gamecenter.core.utils.DisplayUtils;
import com.gh.gamecenter.feature.entity.TagStyleEntity;
@ -70,6 +75,11 @@ public class GameViewUtils {
// 新的游戏标签样式 version>=4.0.0
private static TextView getNewGameTagView(Context context, TagStyleEntity tagEntity, int rightMargin) {
// 参数不全,用旧样式实现
if (TextUtils.isEmpty(tagEntity.getBackground())) {
return getGameTagView(context, tagEntity.getName(), rightMargin, "type", tagEntity);
}
TextView tag = new TextView(context);
updateTagStyle(context, tag, tagEntity, rightMargin);
return tag;
@ -98,6 +108,57 @@ public class GameViewUtils {
textView.setBackground(DrawableView.getServerDrawable(ExtensionsKt.hexStringToIntColor("#" + tagEntity.getBackground(), Color.WHITE)));
}
private static TextView getGameTagView(Context context, String tagStr, int rightMargin, String tagType, TagStyleEntity tagEntity) {
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lparams.rightMargin = rightMargin;
TextView tag = new TextView(context);
tag.setTextSize(TypedValue.COMPLEX_UNIT_SP, 9);
tag.setSingleLine(true);
tag.setText(tagStr);
if ("官方版".equals(tagStr) || "已关注".equals(tagStr)) {
tag.setBackgroundResource(R.drawable.border_green_bg);
tag.setTextColor(ContextCompat.getColor(context, R.color.tag_green));
} else {
String colorStr;
if (!TextUtils.isEmpty(tagType) && "type".equals(tagType) && tagEntity != null) { // 游戏标签
colorStr = "#" + tagEntity.getColor();
GradientDrawable gradientDrawable = new GradientDrawable();
if ("border".equals(tagEntity.getStyle())) {
gradientDrawable.setColor(Color.TRANSPARENT);
gradientDrawable.setStroke(DisplayUtils.dip2px(context, 1f), ExtensionsKt.hexStringToIntColor(colorStr, Color.WHITE));
tag.setTextColor(ExtensionsKt.hexStringToIntColor(colorStr, Color.WHITE));
} else {
gradientDrawable.setColor(ExtensionsKt.hexStringToIntColor(colorStr, Color.WHITE));
gradientDrawable.setShape(GradientDrawable.RECTANGLE);
tag.setTextColor(Color.WHITE);
}
gradientDrawable.setCornerRadius(DisplayUtils.dip2px(3F));
tag.setBackgroundDrawable(gradientDrawable);
} else {
colorStr = TagUtils.getInstance(context).getColor(tagStr);
if (colorStr == null) {
return null;
}
int color = ExtensionsKt.hexStringToIntColor(colorStr, Color.WHITE);
GradientDrawable gradientDrawable = new GradientDrawable();
gradientDrawable.setColor(Color.TRANSPARENT);
gradientDrawable.setStroke(DisplayUtils.dip2px(context, 1f), color);
gradientDrawable.setCornerRadius(DisplayUtils.dip2px(3F));
tag.setBackgroundDrawable(gradientDrawable);
tag.setTextColor(color);
}
}
tag.setLayoutParams(lparams);
tag.setPadding(DisplayUtils.dip2px(context, 4),
0,
DisplayUtils.dip2px(context, 4),
DisplayUtils.dip2px(context, 1));
return tag;
}
public static String getGameTestDate(long testTime) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);

View File

@ -1,20 +1,15 @@
package com.gh.common.util
import com.gh.common.util.ViewPagerFragmentHelper.TYPE_MY_HALO
import com.gh.gamecenter.R
import com.gh.gamecenter.common.entity.Display
import com.gh.gamecenter.common.entity.LinkEntity
import com.gh.gamecenter.common.utils.toJson
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.entity.BottomTab
import com.gh.gamecenter.entity.SubjectRecommendEntity
import com.google.gson.reflect.TypeToken
import com.halo.assistant.HaloApp
object HomeBottomBarHelper {
private const val GAME_BAR_KEY = "game_bar_key"
private const val KEY_HOME_BOTTOM_TAB = "home_bottom_tab"
private const val VIDEO_BAR_KEY = "video_bar_key"
@JvmStatic
fun getDefaultGameBarData(): SubjectRecommendEntity {
@ -35,6 +30,8 @@ object HomeBottomBarHelper {
text = "游戏库",
name = "游戏库",
position = 2,
iconSelect = "https://resource.ghzs.com/image/game/library/entrance/5e183202913fbd002c75f247.png",
iconUnselect = "https://resource.ghzs.com/image/game/library/entrance/5e1831fd913fbd003024641e.png",
animationCode = animationCode,
default = false,
display = Display()
@ -42,37 +39,41 @@ object HomeBottomBarHelper {
}
@JvmStatic
fun getDefaultBottomTabHomeEntity(): BottomTab {
val animationCode = HaloApp.getInstance().application.assets
.open("lottie/tab_home.json")
.bufferedReader().use { it.readText() }
return BottomTab(name = "首页", jsCode = animationCode, iconSelector = R.drawable.selector_ic_home, default = true)
}
@JvmStatic
fun getDefaultBottomTabMineEntity(): BottomTab {
val animationCode = HaloApp.getInstance().application.assets
.open("lottie/tab_mine.json")
.bufferedReader().use { it.readText() }
return BottomTab(name = "我的光环", jsCode = animationCode, iconSelector = R.drawable.selector_ic_user, link = LinkEntity(type = TYPE_MY_HALO))
}
@JvmStatic
fun getDefaultHomeBottomTabData(): List<BottomTab> {
fun getDefaultVideoData(): SubjectRecommendEntity {
try {
val json = SPUtils.getString(KEY_HOME_BOTTOM_TAB)
val json = SPUtils.getString(VIDEO_BAR_KEY)
if (json.isNotEmpty()) {
val type = object : TypeToken<List<BottomTab>>() {}.type
return GsonUtils.gson.fromJson(json, type)
return GsonUtils.fromJson(json, SubjectRecommendEntity::class.java)
}
} catch (ignore: Exception) {
}
return listOf(getDefaultBottomTabHomeEntity(), getDefaultBottomTabMineEntity())
return getDefaultVideoEntity()
}
@JvmStatic
fun updateDefaultHomeBottomTabData(data: List<BottomTab>) {
SPUtils.setString(KEY_HOME_BOTTOM_TAB, data.toJson())
fun getDefaultVideoEntity(): SubjectRecommendEntity {
val animationCode = HaloApp.getInstance().application.assets
.open("lottie/tab_video.json")
.bufferedReader().use { it.readText() }
return SubjectRecommendEntity(
type = "video_stream",
text = "视频",
name = "视频",
position = 4,
animationCode = animationCode,
default = false,
display = Display()
)
}
@JvmStatic
fun updateDefaultGameBarData(data: SubjectRecommendEntity) {
SPUtils.setString(GAME_BAR_KEY, data.toJson())
}
@JvmStatic
fun updateDefaultVideoBarData(data: SubjectRecommendEntity) {
SPUtils.setString(VIDEO_BAR_KEY, data.toJson())
}
}

View File

@ -1,18 +1,13 @@
package com.gh.common.util
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.tracker.Tracker
import com.gh.gamecenter.common.utils.toastInInternalRelease
import com.gh.gamecenter.common.utils.tryCatchInRelease
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.utils.MD5Utils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.entity.HomePluggableFilterEntity
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.home.PluginDisplayStatus
import com.gh.gamecenter.room.AppDatabase
/**
* 插件化区域辅助类
* 首页插件化区域辅助类
*/
object HomePluggableHelper {
@ -23,67 +18,19 @@ object HomePluggableHelper {
val apkList = gameEntity.getApk()
if (apkList.isNotEmpty()) {
val apk = apkList.first()
val apkHash = MD5Utils.getContentMD5(gameEntity.id + apk.version)
val tag = if (isNever) "never" else apkHash
runOnIoThread {
tryCatchInRelease {
val filterData = mHomePluggableFilterDao.getDataByPkgName(apk.packageName)
if (filterData != null && !filterData.tag.contains(tag)) {
filterData.tag = filterData.tag + "," + tag
mHomePluggableFilterDao.addData(filterData)
} else {
mHomePluggableFilterDao.addData(
HomePluggableFilterEntity(
pkgName = apk.packageName,
tag = tag,
active = true
)
)
}
}
val tag = if (isNever) "never" else apk.version ?: ""
tryCatchInRelease {
mHomePluggableFilterDao.addData(
HomePluggableFilterEntity(
pkgName = apk.packageName,
tag = tag,
active = isNever
)
)
}
}
}
/**
* 获取插件化区域显示样式
*/
fun getPluginDisplayedStyle(pluginList: List<Any>?): PluginDisplayStatus {
if (pluginList.isNullOrEmpty()) {
return PluginDisplayStatus.DEFAULT
}
val shouldShowCollapsedStyle = shouldShowCollapsedStyle()
return if (shouldShowCollapsedStyle) {
PluginDisplayStatus.CLOSE
} else {
setPluginAreaShowed()
if (pluginList.size > 2) {
PluginDisplayStatus.OPEN_TWO_AND_BUTTON
} else {
PluginDisplayStatus.OPEN
}
}
}
/**
* 是否需要把插件化区域显示为收起样式
* https://jira.shanqu.cc/browse/GHZS-4725
*/
private fun shouldShowCollapsedStyle(): Boolean {
val launchId = SPUtils.getString(Constants.SP_PLUGIN_AREA_SHOWED_LAUNCH_ID)
return if (launchId.isEmpty()) {
false
} else {
Tracker.launchId != launchId
}
}
private fun setPluginAreaShowed() {
SPUtils.setString(Constants.SP_PLUGIN_AREA_SHOWED_LAUNCH_ID, Tracker.launchId)
}
@JvmStatic
fun showHomePluggable(gameEntity: GameEntity): Boolean {
val apkList = gameEntity.getApk()
@ -91,9 +38,9 @@ object HomePluggableHelper {
val apk = apkList.first()
tryCatchInRelease {
val filterData = mHomePluggableFilterDao.getDataByPkgName(apk.packageName)
if (filterData != null) {
if (filterData?.active == true) {
val filterTag = filterData.tag
return !filterTag.contains("never") && !filterTag.contains(MD5Utils.getContentMD5(gameEntity.id + apk.version))
return filterTag != "never" && apk.version != filterTag
}
}
}
@ -108,4 +55,20 @@ object HomePluggableHelper {
return emptyList()
}
@JvmStatic
fun activationFilterData() {
try {
val filterList = mHomePluggableFilterDao.getDataByActive(false)
if (filterList != null) {
for (entity in filterList) {
entity.active = true
}
mHomePluggableFilterDao.addData(filterList)
}
} catch (e: Exception) {
e.printStackTrace()
toastInInternalRelease("插件化筛选出现异常")
}
}
}

View File

@ -50,7 +50,7 @@ public class InstallUtils {
public void handleMessage(Message msg) {
if (msg.what == INSTALL_WHAT && packageManager != null) {
ArrayList<String> list = new ArrayList<>();
List<PackageInfo> packageInfos = PackageHelper.INSTANCE.getInstalledPackages(context, 0);
List<PackageInfo> packageInfos = PackageUtils.getInstalledPackages(context, 0);
for (PackageInfo packageInfo : packageInfos) {
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
list.add(packageInfo.packageName);

View File

@ -768,7 +768,7 @@ public class LibaoUtils {
}
public static boolean isAppInstalled(Context context, String packageName) {
List<PackageInfo> pinfo = PackageHelper.INSTANCE.getInstalledPackages(context, 0);
List<PackageInfo> pinfo = PackageUtils.getInstalledPackages(context, 0);
if (pinfo != null) {
for (int i = 0; i < pinfo.size(); i++) {
String pn = pinfo.get(i).packageName;

View File

@ -566,7 +566,7 @@ public class MessageShareUtils {
String path;
// 安卓11无法访问Android/data目录
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath() + "/ShareImg/";
path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/ShareImg/";
} else {
path = context.getExternalCacheDir().getPath() + "/ShareImg/";
}

View File

@ -2,53 +2,23 @@ package com.gh.common.util
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.pm.PermissionInfo
import android.os.Build
import android.provider.Settings
import com.gh.common.constant.Config
import com.gh.gamecenter.common.utils.PermissionHelper.isGetInstalledListPermissionDisabled
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.feature.entity.SettingsEntity
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStreamReader
import kotlin.collections.ArrayList
import kotlin.collections.HashSet
object PackageHelper {
private const val TAG = "PackageHelper"
private const val SP_GET_INSTALLED_API_AGREED = "get_installed_api_agreed"
private const val UNKNOWN = -1
private const val UNSUPPORTED = 0
private const val SUPPORTED = 1
private var lastInstalledPackageListTime = 0L
private var installedPackageList: List<PackageInfo> = arrayListOf()
private var isGetInstalledPackagesApiAgreed = false
private var isGetInstalledListPermissionSupported = UNKNOWN // 设备是否支持禁用获取已安装应用列表。-1 代表支持情况未知0 代表不支持, 1 代表支持
// 评论黑名单包名列表,避免用户安装了 Xposed Installer 这样的工具,也能在包含该安装包的游戏详情页评论
private var _commentPackageNameBlackList = arrayListOf<String>()
val commentPackageNameBlackList: ArrayList<String> = _commentPackageNameBlackList
var commentPackageNameBlackList = arrayListOf<String>()
// 关闭下载的包列表
private var _downloadPackageNameBlackList = arrayListOf<String>()
val downloadPackageNameBlackList: ArrayList<String> = _downloadPackageNameBlackList
var downloadPackageNameBlackList = arrayListOf<String>()
// 本地已安装的包去掉关闭下载的包后的列表
private var _validLocalPackageNameSet = hashSetOf<String>()
val validLocalPackageNameSet: HashSet<String> = _validLocalPackageNameSet
var validLocalPackageNameSet = hashSetOf<String>()
// 游戏包名匹配列表
private var _relatedPackageList = arrayListOf<SettingsEntity.GameWithPackages>()
val relatedPackageList: ArrayList<SettingsEntity.GameWithPackages> = _relatedPackageList
var relatedPackageList = arrayListOf<SettingsEntity.GameWithPackages>()
// 本地已安装包的列表
var localPackageNameSet = hashSetOf<String>()
@ -68,26 +38,33 @@ object PackageHelper {
}
@JvmStatic
fun refreshList() {
Config.getSettings()?.gameCommentBlackList?.let { _commentPackageNameBlackList = ArrayList(it) }
Config.getSettings()?.gameDownloadBlackList?.let { _downloadPackageNameBlackList = ArrayList(it) }
Config.getSettings()?.gamePackageMatch?.let { _relatedPackageList = ArrayList(it) }
fun initList() {
Config.getSettings()?.gameCommentBlackList?.let {
commentPackageNameBlackList = ArrayList(it)
}
Config.getSettings()?.gameDownloadBlackList?.let {
downloadPackageNameBlackList = ArrayList(it)
}
Config.getSettings()?.gamePackageMatch?.let {
relatedPackageList = ArrayList(it)
}
Config.getSettings()?.gameDownloadBlackList
updateValidPackageNameList()
}
private fun updateValidPackageNameList() {
_validLocalPackageNameSet =
validLocalPackageNameSet =
localPackageNameSet.filterNot { p -> downloadPackageNameBlackList.contains(p) }.toHashSet()
}
/**
/*
* 获取所有已安装的软件的包名、版本(非系统应用)
*/
private fun getAllPackageName(context: Context): HashSet<String> {
val set = HashSet<String>()
return try {
val packageInfos = getInstalledPackages(context, 0)
val packageInfos = PackageUtils.getInstalledPackages(context, 0)
for (packageInfo in packageInfos) {
if (packageInfo.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM == 0) {
if (context.packageName != packageInfo.packageName) {
@ -102,154 +79,4 @@ object PackageHelper {
}
}
/**
* 弃用已安装列表缓存
*/
fun dumpInstalledListCache() {
lastInstalledPackageListTime = 0
}
/**
* 用户是否已经允许了调用获取已安装应用列表接口
* 优先用内存的值,没有再从 SP 中获取并更新
*/
fun isGetInstalledPackagesApiAgreed(): Boolean {
return isGetInstalledPackagesApiAgreed
|| (SPUtils.getBoolean(SP_GET_INSTALLED_API_AGREED).also { isGetInstalledPackagesApiAgreed = it })
}
/**
* 同意使用已安装应用列表 API
*/
fun agreeOnGetInstalledPackagesApi() {
isGetInstalledPackagesApiAgreed = true
SPUtils.setBoolean(SP_GET_INSTALLED_API_AGREED, true)
}
/**
* 获取已安装应用列表
*/
fun getInstalledPackages(context: Context?, flags: Int): List<PackageInfo> {
Utils.log(TAG, "即将获取已安装应用列表")
// Utils.log(TAG, "即将获取已安装应用列表" + Thread.currentThread().getStackTrace().contentToString().replace( ',', '\n' ))
// 用户未同意使用已安装应用列表 API返回空列表
if (!isGetInstalledPackagesApiAgreed()) {
Utils.log(TAG, "用户未同意使用已安装应用列表 API返回空列表")
return installedPackageList
}
// 简单 debounce 过于频繁的获取已安装应用列表调用
if (System.currentTimeMillis() - lastInstalledPackageListTime < 3000 && installedPackageList.isNotEmpty()) {
Utils.log(TAG, "使用了缓存的已安装应用列表")
return installedPackageList
}
var shouldGetNewInstalledPackagedList = false
// 当前设备是否支持限制获取已安装应用列表的功能
if (isSupportGetInstalledAppsPermission(context!!)) {
Utils.log(TAG, "当前设备支持限制获取已安装应用列表的功能")
// 当前设备是否支持禁用了获取已安装应用列表
if (!isGetInstalledListPermissionDisabled(context)) {
Utils.log(TAG, "当前设备没有限制获取已安装应用列表的功能")
shouldGetNewInstalledPackagedList = true
} else {
Utils.log(TAG, "当前设备已限制获取已安装应用列表的功能")
}
} else {
Utils.log(TAG, "当前设备不支持限制获取已安装应用列表的功能")
shouldGetNewInstalledPackagedList = true
}
if (shouldGetNewInstalledPackagedList) {
lastInstalledPackageListTime = System.currentTimeMillis()
installedPackageList = getInstalledPackagesInternal(context, flags)
}
return installedPackageList
}
/**
* 是否支持动态获取已安装应用列表权限
*/
fun isSupportGetInstalledAppsPermission(context: Context): Boolean {
// 若存在缓存,直接返回缓存结果。
if (isGetInstalledListPermissionSupported != UNKNOWN) {
return isGetInstalledListPermissionSupported != UNSUPPORTED
}
try {
// 根据官方提供的方法来判定是否支持限制获取已安装应用列表
val flag =
Settings.Secure.getInt(context.contentResolver, "oem_installed_apps_runtime_permission_enable", 0)
if (flag == 1) {
isGetInstalledListPermissionSupported = SUPPORTED
return true
}
// 部分未升级的手机没有上面配置项,有定义下面危险权限也认为是支持设备软件列表管控
val packageManager = context.packageManager
val permissionInfo = packageManager.getPermissionInfo("com.android.permission.GET_INSTALLED_APPS", 0)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
if (permissionInfo.protection == PermissionInfo.PROTECTION_DANGEROUS) {
isGetInstalledListPermissionSupported = SUPPORTED
return true
} else {
isGetInstalledListPermissionSupported = UNSUPPORTED
return false
}
} else {
isGetInstalledListPermissionSupported = UNSUPPORTED
return false
}
} catch (e: PackageManager.NameNotFoundException) {
isGetInstalledListPermissionSupported = UNSUPPORTED
return false
}
}
/**
* 在5.1系统手机使用PackageManager获取已安装应用容易发生Package manager has died异常
* https://stackoverflow.com/questions/13235793/transactiontoolargeeception-when-trying-tÏo-get-a-list-of-applications-installed/30062632#30062632
*/
private fun getInstalledPackagesInternal(context: Context, flags: Int): List<PackageInfo> {
Utils.log(TAG, "调用系统 API 获取已安装应用列表")
val pm = context.packageManager
try {
return pm.getInstalledPackages(flags)
} catch (ignored: java.lang.Exception) {
//we don't care why it didn't succeed. We'll do it using an alternative way instead
}
// use fallback:
val process: Process
val result: MutableList<PackageInfo> = java.util.ArrayList()
var bufferedReader: BufferedReader? = null
try {
process = Runtime.getRuntime().exec("pm list packages")
bufferedReader = BufferedReader(InputStreamReader(process.inputStream))
var line: String
while ((bufferedReader.readLine().also { line = it }) != null) {
val packageName = line.substring(line.indexOf(':') + 1)
val packageInfo = pm.getPackageInfo(packageName, flags)
result.add(packageInfo)
}
process.waitFor()
} catch (e: java.lang.Exception) {
e.printStackTrace()
if (e is InterruptedException) {
Thread.currentThread().interrupt()
}
} finally {
if (bufferedReader != null) try {
bufferedReader.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
return result
}
}

View File

@ -24,6 +24,7 @@ import com.gh.gamecenter.vpn.VpnHelper
import com.gh.vspace.VHelper
import com.halo.assistant.HaloApp
import com.lightgame.download.DownloadEntity
import com.lightgame.download.FileUtils
import com.lightgame.utils.Utils
import java.io.File

View File

@ -25,10 +25,12 @@ import androidx.webkit.WebViewCompat;
import com.android.apksig.ApkVerifier;
import com.android.apksig.internal.apk.ApkSigningBlockUtilsLite;
import com.g00fy2.versioncompare.Version;
import com.gh.common.filter.RegionSettingHelper;
import com.gh.common.xapk.XapkInstaller;
import com.gh.gamecenter.BuildConfig;
import com.gh.gamecenter.common.constant.Constants;
import com.gh.gamecenter.common.utils.ExtensionsKt;
import com.gh.gamecenter.common.utils.PackageFlavorHelper;
import com.gh.gamecenter.common.utils.PermissionHelper;
import com.gh.gamecenter.core.utils.MD5Utils;
import com.gh.gamecenter.core.utils.SentryHelper;
@ -67,8 +69,16 @@ import java.util.zip.ZipFile;
public class PackageUtils {
private static long mLastInstalledPackageListTime = 0L;
private static List<PackageInfo> mInstalledPackageList = null;
public static final String publicKey = "OpenSSLRSAPublicKey{modulus=a8c4bb5748fec8d5c35db1a7a182d41ba4721a91131a417330af79ef4ddb43f9fa0ff4907b0a613bfe152de0ed8fc1b2e6f94a908aa98a5f7adc1ce814ba7ec919d75d9910bdfd8649b4789da6a90ffb61f0d23ac4f828a78fcd0d6f6120c1c43c1f87f7498a89eb40ca8e32dfc2f9d5c10d612b95192870223674e241e53305abf320d7eed76ded398778576e4db7b17b3bc6a792f13de5e43a6a5fae4276c73e6990ce97f68dff0ec16fc9594f175c8d49cd0d7877340d9de60942ca0efc737e50b6c295dfe0713e4532b4e810e1ea11b702b4a27753e41559cbceb247e7f044ec4e3ab2e8bccd8b9fd71286e63307550bcde86deee95adb8133076269135b,publicExponent=10001}";
private static final String TAG = "PackageUtils";
// 设备是否支持禁用获取已安装应用列表。-1 代表支持情况未知0 代表不支持, 1 代表支持
private static int mIsSupportGetInstalledListPermission = -1;
public static String getInstallPackageInfoSourceDir(String packageName) {
try {
return HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
@ -141,8 +151,14 @@ public class PackageUtils {
}
}
// 镜像游戏,使用镜像 Apk 替换掉原来的 ApkNormal
if (RegionSettingHelper.shouldThisGameDisplayMirrorInfo(gameEntity.getId())) {
gameEntity.setApkNormal(gameEntity.getApk());
}
// 非插件游戏更新
for (ApkEntity apkEntity : gameEntity.getApk()) {
for (ApkEntity apkEntity : gameEntity.getApkNormal()) {
// ghVersion 不存在即是非插件游戏
if (TextUtils.isEmpty(apkEntity.getGhVersion())) {
int versionCodeFromRequest = apkEntity.getVersionCode();
@ -283,13 +299,11 @@ public class PackageUtils {
/*
* 判断是否为光环签名
* 判断是否是插件包
*/
public static boolean isSignedByGh(Context context, String packageName) {
String signature = getApkSignatureByPackageName(context, packageName)[0];
// 判断当前已安装应用是否为光环签名。若签名列表为空,直接判断为光环签名
return signature == null || SignatureRepository.isSignEmpty() || SignatureRepository.isSignMatched(signature);
return publicKey.equals(signature);
}
/*
@ -446,7 +460,7 @@ public class PackageUtils {
}
// 判断当前已安装应用是否为光环签名
if (isSignedByGh(context, packageName)) {
if (publicKey.equals(getApkSignatureByPackageName(context, packageName)[0])) {
return true;
}
@ -670,7 +684,7 @@ public class PackageUtils {
*/
public static ArrayList<String> getAllPackageName(Context context) {
ArrayList<String> list = new ArrayList<>();
List<PackageInfo> packageInfos = PackageHelper.INSTANCE.getInstalledPackages(context, 0);
List<PackageInfo> packageInfos = getInstalledPackages(context, 0);
for (PackageInfo packageInfo : packageInfos) {
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
if (!context.getPackageName().equals(packageInfo.packageName)) {
@ -683,7 +697,7 @@ public class PackageUtils {
public static ArrayList<String> getAllPackageNameIncludeGh(Context context) {
ArrayList<String> list = new ArrayList<>();
List<PackageInfo> packageInfos = PackageHelper.INSTANCE.getInstalledPackages(context, 0);
List<PackageInfo> packageInfos = getInstalledPackages(context, 0);
for (PackageInfo packageInfo : packageInfos) {
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
list.add(packageInfo.packageName);
@ -697,9 +711,11 @@ public class PackageUtils {
*/
public static ArrayList<String> getAllPackageNameIncludeSystemApps(Context context) {
ArrayList<String> list = new ArrayList<>();
List<PackageInfo> packageInfos = PackageHelper.INSTANCE.getInstalledPackages(context, 0);
List<PackageInfo> packageInfos = getInstalledPackages(context, 0);
for (PackageInfo packageInfo : packageInfos) {
list.add(packageInfo.packageName);
if (!context.getPackageName().equals(packageInfo.packageName)) {
list.add(packageInfo.packageName);
}
}
return list;
}
@ -708,7 +724,7 @@ public class PackageUtils {
JSONArray jsonArray = new JSONArray();
try {
PackageManager pm = context.getPackageManager();
List<PackageInfo> packageInfos = PackageHelper.INSTANCE.getInstalledPackages(context, 0);
List<PackageInfo> packageInfos = getInstalledPackages(context, 0);
for (PackageInfo packageInfo : packageInfos) {
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
JSONObject jsonObject = new JSONObject();
@ -749,6 +765,7 @@ public class PackageUtils {
}
}
/**
* 启动应用
* 请使用 PackageLauncher.launchApp()
@ -768,6 +785,22 @@ public class PackageUtils {
}
}
/*
* 根据包名,获取软件名称
*/
public static String getNameByPackageName(Context context, String packageName) {
try {
PackageManager pm = context.getApplicationContext().getPackageManager();
ApplicationInfo applicationInfo = pm.getApplicationInfo(
packageName, 0);
return applicationInfo.loadLabel(pm).toString();
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return null;
}
/**
* todo 统一判断
* <p>
@ -862,6 +895,37 @@ public class PackageUtils {
&& !PackageUtils.isSignedByGh(HaloApp.getInstance().getApplication(), apkEntity.getPackageName());
}
/**
* 获取调用者的进程名
*
* @param context 调用者的上下文
* @return 进程名
*/
public static String obtainProcessName(Context context) {
if (PackageFlavorHelper.IS_TEST_FLAVOR) {
try {
final int pid = android.os.Process.myPid();
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> listTaskInfo = am.getRunningAppProcesses();
if (listTaskInfo != null && !listTaskInfo.isEmpty()) {
for (ActivityManager.RunningAppProcessInfo info : listTaskInfo) {
if (info != null && info.pid == pid) {
return info.processName;
}
}
}
} catch (Exception e) {
// 遇到异常了让这次调用正常执行
e.printStackTrace();
return BuildConfig.APPLICATION_ID;
}
} else {
return null;
}
return null;
}
/**
* 应用是否在前台运行
*/
@ -886,8 +950,8 @@ public class PackageUtils {
String packageName = context.getApplicationContext().getPackageName();
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
// The name of the process that this object is associated with.
if (appProcess.processName.equals(packageName)
&& appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
if (appProcess.processName.equals(packageName) && appProcess.importance
== ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
return true;
}
}
@ -898,6 +962,132 @@ public class PackageUtils {
return false;
}
/**
* 弃用已安装列表缓存
*/
public static void dumpInstalledListCache() {
mLastInstalledPackageListTime = 0;
}
public static List<PackageInfo> getInstalledPackages(Context context, int flags) {
Utils.log(TAG, "即将获取已安装应用列表");
// 简单 debounce 掉过于频繁的调用获取已安装列表调用
if (System.currentTimeMillis() - mLastInstalledPackageListTime < 1000
&& mInstalledPackageList != null
&& mInstalledPackageList.size() > 0) {
Utils.log(TAG, "使用了缓存的已安装应用列表");
return new ArrayList<>(mInstalledPackageList);
}
// 是否需要调用系统 API 获取最新的已安装应用列表
boolean shouldGetNewInstalledPackagedList = false;
// 当前设备是否支持限制获取已安装应用列表的功能
if (isSupportGetInstalledAppsPermission(context)) {
Utils.log(TAG, "当前设备支持限制获取已安装应用列表的功能");
// 当前设备是否支持禁用了获取已安装应用列表
if (!PermissionHelper.isGetInstalledListPermissionDisabled(context)) {
Utils.log(TAG, "当前设备没有限制获取已安装应用列表的功能");
shouldGetNewInstalledPackagedList = true;
} else {
Utils.log(TAG, "当前设备已限制获取已安装应用列表的功能");
}
} else {
Utils.log(TAG, "当前设备不支持限制获取已安装应用列表的功能");
shouldGetNewInstalledPackagedList = true;
}
if (shouldGetNewInstalledPackagedList) {
mLastInstalledPackageListTime = System.currentTimeMillis();
mInstalledPackageList = getInstalledPackagesInternal(context, flags);
}
if (mInstalledPackageList == null) {
mInstalledPackageList = new ArrayList<>();
}
return mInstalledPackageList;
}
public static boolean isSupportGetInstalledAppsPermission(Context context) {
// 若存在缓存,直接返回缓存结果。为 0 代表不支持,为 1 代表支持
if (mIsSupportGetInstalledListPermission != -1) {
return mIsSupportGetInstalledListPermission != 0;
}
try {
// 根据官方提供的方法来判定是否支持限制获取已安装应用列表
int flag = Settings.Secure.getInt(context.getContentResolver(), "oem_installed_apps_runtime_permission_enable", 0);
if (flag == 1) {
mIsSupportGetInstalledListPermission = 1;
return true;
}
// 部分未升级的手机没有上面配置项,有定义下面危险权限也认为是支持设备软件列表管控
PackageManager packageManager = context.getPackageManager();
PermissionInfo permissionInfo = packageManager.getPermissionInfo("com.android.permission.GET_INSTALLED_APPS", 0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
if (permissionInfo.getProtection() == PermissionInfo.PROTECTION_DANGEROUS) {
mIsSupportGetInstalledListPermission = 1;
return true;
} else {
mIsSupportGetInstalledListPermission = 0;
return false;
}
} else {
mIsSupportGetInstalledListPermission = 0;
return false;
}
} catch (NameNotFoundException e) {
mIsSupportGetInstalledListPermission = 0;
return false;
}
}
/**
* 在5.1系统手机使用PackageManager获取已安装应用容易发生Package manager has died异常
* https://stackoverflow.com/questions/13235793/transactiontoolargeeception-when-trying-tÏo-get-a-list-of-applications-installed/30062632#30062632
*/
private static List<PackageInfo> getInstalledPackagesInternal(Context context, int flags) {
Utils.log(TAG, "调用系统 API 获取已安装应用列表");
final PackageManager pm = context.getPackageManager();
try {
return pm.getInstalledPackages(flags);
} catch (Exception ignored) {
//we don't care why it didn't succeed. We'll do it using an alternative way instead
}
// use fallback:
Process process;
List<PackageInfo> result = new ArrayList<>();
BufferedReader bufferedReader = null;
try {
process = Runtime.getRuntime().exec("pm list packages");
bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = bufferedReader.readLine()) != null) {
final String packageName = line.substring(line.indexOf(':') + 1);
final PackageInfo packageInfo = pm.getPackageInfo(packageName, flags);
result.add(packageInfo);
}
process.waitFor();
} catch (Exception e) {
e.printStackTrace();
if (e instanceof InterruptedException) {
Thread.currentThread().interrupt();
}
} finally {
if (bufferedReader != null)
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
public static String getWebviewPath(Context context) {
final PackageInfo webViewPackageInfo = WebViewCompat.getCurrentWebViewPackage(context);
return webViewPackageInfo != null ? webViewPackageInfo.applicationInfo.sourceDir : null;

View File

@ -1,7 +1,5 @@
package com.gh.common.util
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.gh.gamecenter.core.utils.CurrentActivityHolder
import com.gh.download.DownloadManager
import com.gh.gamecenter.ShellActivity
@ -16,19 +14,10 @@ import com.lightgame.download.DownloadStatus
object RealNameHelper {
private var pendingInstallPkgPath = ""
var pendingInstallPkgPath = ""
// 0表示未实名1表示未成年2表示成年
private var certificationStatus: Int = 0
private val _realNameInfoUpdateLiveData = MutableLiveData<Any>()
val realNameInfoUpdateLiveData = _realNameInfoUpdateLiveData as LiveData<Any>
fun updatePendingInstallPkgPath(path: String) {
pendingInstallPkgPath = path
}
fun getPendingInstallPkgPath() = pendingInstallPkgPath
private var mCertificationStatus: Int = 0
/**
* 弹未成年人不能下载游戏弹窗
@ -71,12 +60,14 @@ object RealNameHelper {
downloadEntity?.let {
NewLogUtils.logCertificationTrigger(downloadEntity.gameId, downloadEntity.name)
SensorsBridge.trackVerificationDialogShow(
gameId = downloadEntity.gameId,
gameName = downloadEntity.name ?: "",
gameType = downloadEntity.meta[Constants.GAME_CATEGORY_IN_CHINESE] ?: "",
articleType = "",
verificationType = "游戏实名"
SensorsBridge.trackEvent(
"VerificationDialogShow",
"game_id",
downloadEntity.gameId,
"game_name",
downloadEntity.name ?: "",
"game_type",
downloadEntity.meta[Constants.GAME_CATEGORY_IN_CHINESE] ?: ""
)
}
@ -105,7 +96,6 @@ object RealNameHelper {
currentActivity,
ShellActivity.Type.REAL_NAME_INFO
).apply {
putExtra(EntranceConsts.KEY_SOURCE_ENTRANCE, "游戏实名")
putExtra(EntranceConsts.KEY_IS_FORCED_TO_CERTIFICATE, true)
putExtra(EntranceConsts.KEY_IS_FORCED_TO_CERTIFICATE_BUT_WITH_BACKDOOR, !isForced)
}
@ -114,11 +104,11 @@ object RealNameHelper {
pendingInstallPkgPath = downloadEntity.path
}
NewLogUtils.logCertificationHintDialogOptionsClicked("前往实名认证")
SensorsBridge.trackVerificationPopupClick("前往实名认证")
SensorsBridge.trackEvent("VerificationPopupClick", "button_name", "前往实名认证")
},
cancelClickCallback = {
NewLogUtils.logCertificationHintDialogOptionsClicked("取消")
SensorsBridge.trackVerificationPopupClick("取消")
SensorsBridge.trackEvent("VerificationPopupClick", "button_name", "取消")
if (!isForced) {
DownloadManager.getInstance()
.resumeAllInvisiblePendingTask()
@ -141,15 +131,11 @@ object RealNameHelper {
}
}
fun onRealNameInfoUpdated() {
_realNameInfoUpdateLiveData.postValue(Any())
}
/**
* 获取实名状态 0表示未实名1表示未成年2表示成年
*/
fun getCertificationStatus(): Int {
return certificationStatus
return mCertificationStatus
}
/**
@ -157,7 +143,7 @@ object RealNameHelper {
*/
@JvmStatic
fun updateCertificationStatus(newCertificationStatus: Int) {
certificationStatus = newCertificationStatus
mCertificationStatus = newCertificationStatus
}
}

View File

@ -1,7 +1,7 @@
package com.gh.common.util
import com.gh.common.dialog.DeviceRemindDialog
import com.gh.gamecenter.common.constant.Constants
import com.gh.common.dialog.DeviceRemindDialog
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.core.utils.TimeUtils
@ -39,7 +39,7 @@ object RecommendPopupHelper {
//判断是否符合安装包大小限制
val minSize = entity.recommendPackage.minSize
val sizeStr = gameEntity.getApk().firstOrNull()?.size ?: continue
val sizeStr = gameEntity.getApk()[0].size ?: continue
val size = sizeStr.substring(0, sizeStr.length - 2).toFloat()
if (size < minSize) continue

View File

@ -69,9 +69,9 @@ object ReservationHelper {
@JvmStatic
@SuppressLint("CheckResult")
fun reserve(context: Context, game: GameEntity?, sourceEntrance: String = "其他", callback: EmptyCallback) {
fun reserve(context: Context, gameId: String, gameName: String, callback: EmptyCallback) {
val requestMap = hashMapOf<String, String>()
requestMap["game_id"] = game?.id ?: ""
requestMap["game_id"] = gameId
RetrofitManager.getInstance().api
.createNewGameReservation(requestMap.createRequestBody())
.compose(singleToMain())
@ -81,18 +81,14 @@ object ReservationHelper {
SensorsBridge.trackEvent(
"AppointmentGameResult",
"game_name",
game?.name ?: "",
gameName,
"game_id",
game?.id ?: "",
"game_type",
game?.categoryChinese ?: "",
gameId,
"result",
"成功",
"source_entrance",
sourceEntrance
"成功"
)
ReservationRepository.addReservationToMemoryAndRefresh(game?.id ?: "")
ReservationRepository.addReservationToMemoryAndRefresh(gameId)
callback.onCallback()
val wechatConfig = SPUtils.getString(Constants.SP_WECHAT_CONFIG).toObject<WechatConfigEntity>()
wechatConfig?.run {
@ -126,15 +122,11 @@ object ReservationHelper {
SensorsBridge.trackEvent(
"AppointmentGameResult",
"game_name",
game?.name ?: "",
gameName,
"game_id",
game?.id ?: "",
"game_type",
game?.categoryChinese ?: "",
gameId,
"result",
"失败",
"source_entrance",
sourceEntrance
"失败"
)
ToastUtils.showToast(exception.message ?: "")
}

View File

@ -1,65 +0,0 @@
package com.gh.common.util
import android.annotation.SuppressLint
import com.gh.gamecenter.common.entity.SignatureEntity
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.common.utils.toJson
import com.gh.gamecenter.common.utils.toObject
import com.gh.gamecenter.core.utils.MD5Utils
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.retrofit.RetrofitManager
/**
* 存储光环网游使用的签名
*/
object SignatureRepository {
private const val SP_SIGN_DIGEST_LIST = "sign_digest_list"
private var signDigestList: ArrayList<String>? = null
@SuppressLint("CheckResult")
fun init() {
RetrofitManager.getInstance()
.newApi
.ghSignature
.compose(singleToMain())
.subscribe(object : BiResponse<ArrayList<SignatureEntity>>() {
override fun onSuccess(data: ArrayList<SignatureEntity>) {
signDigestList = ArrayList()
for (i in data) {
signDigestList?.add(i.signMd5)
}
SPUtils.setString(SP_SIGN_DIGEST_LIST, signDigestList?.toJson() ?: "")
}
override fun onFailure(exception: Exception) {
super.onFailure(exception)
signDigestList = SPUtils.getString(SP_SIGN_DIGEST_LIST).toObject()
}
})
}
/**
* 签名列表是否为空
*/
@JvmStatic
fun isSignEmpty(): Boolean {
return signDigestList.isNullOrEmpty()
}
/**
* 签名是否匹配已知的签名
*/
@JvmStatic
fun isSignMatched(sign: String): Boolean {
val signDigest = MD5Utils.getContentMD5(sign)
return signDigestList?.contains(signDigest) == true
}
}

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