Compare commits

..

4 Commits

Author SHA1 Message Date
1b1a368047 feat: va_core 启用sentry 2024-08-21 09:52:08 +08:00
30135bdb8f Merge branch 'fix/va-install-sdcard' into 'dev'
fix: 本地测试手动安装游戏包安装到一体化畅玩

See merge request halo/android/assistant-android!1848
2024-08-20 16:14:50 +08:00
f8ac85d29c fix: 本地测试手动安装游戏包安装到一体化畅玩 2024-08-20 16:13:46 +08:00
39bba71e7a chore: 版本更新至 5.38.0
Signed-off-by: chenjuntao <chenjuntao@ghzhushou.com>
2024-08-13 13:44:56 +08:00
66 changed files with 286 additions and 1108 deletions

View File

@ -72,7 +72,6 @@ android_build:
only:
- dev
- release
- feat/GHZSCY-6644
# 代码检查
sonarqube_analysis:
@ -157,5 +156,4 @@ oss-upload&send-email:
- /usr/local/bin/python /ci-android-mail-jira-comment.py
only:
- dev
- release
- feat/GHZSCY-6644
- release

View File

@ -32,43 +32,11 @@ class ExternalGameUsage : ITestCase {
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 })
}
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位插件")
// TODO: 补充debug插件更新
ToastUtils.showToast("暂未实现debug功能")
} 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()) {
// TODO: 补充debug插件更新
ToastUtils.showToast("暂未实现debug功能")
} else {
ToastUtils.showToast("data/local/tmp没有push文件")
}
}
}
}
}

View File

@ -1,7 +1,12 @@
package com.gh.vspace.installexternalgames
import android.Manifest
import android.app.Dialog
import android.content.ComponentName
import android.content.pm.PackageManager
import android.os.Bundle
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import com.gh.common.util.DialogUtils
import com.gh.gamecenter.R
@ -40,6 +45,19 @@ class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
private lateinit var dialog: Dialog
private val requestPermissionLauncher = registerForActivityResult<String, Boolean>(
ActivityResultContracts.RequestPermission()
) { result ->
if (result == true) {
// grant
mViewModel.scanPaths()
} else {
// not grant
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setNavigationTitle(getString(com.gh.gamecenter.R.string.title_install_external_game))
@ -56,11 +74,30 @@ class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
)
adapter.notifyDataSetChanged()
}
mViewModel.scanPaths()
requestStoragePermission()
}
private fun requestStoragePermission() {
when {
ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.READ_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_GRANTED -> {
mViewModel.scanPaths()
}
shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE) -> {
requestPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
}
else -> {
requestPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
}
}
}
private fun initView() {
dialog = DialogUtils.showWaitDialog(requireContext(), "")
mBinding.externalGamesList.let {
@ -94,9 +131,11 @@ class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
OnItemClickListener.ClickType.CLICK_INSTALL -> {
install(externalGameUiState)
}
OnItemClickListener.ClickType.CLICK_UNINSTALL -> {
uninstall(externalGameUiState)
}
OnItemClickListener.ClickType.CLICK_START -> {
start(externalGameUiState)
}
@ -104,9 +143,8 @@ 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.disableLaunchGameAfterInstallation()
VHelper.install(requireContext(), DownloadEntity().apply {
externalGameUiState.externalGameEntity.apply {
packageName = apkPackageName
@ -114,20 +152,12 @@ class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
}
}, true)
if (VHelper.showDialogIfVSpaceIsNeeded(
requireContext(),
"",
externalGameUiState.externalGameEntity.appName,
"",
bit = bit
)
) return
dialog.show()
externalGameUiState.externalGameEntity.let {
val intent = VirtualAppManager.getInstallIntent(context, it.apkPath, it.apkPackageName)
requireActivity().startActivity(intent)
VHelper.newCwValidateVspaceBeforeAction(
requireContext(),null,
) {
dialog.show()
}
}
private fun uninstall(externalGameUiState: ExternalGameUiState) {
@ -158,6 +188,12 @@ class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
com.gh.gamecenter.BuildConfig.VA_VERSION_NAME,
HaloApp.getInstance().oaid
)
intent.setComponent(
ComponentName(
com.gh.gamecenter.BuildConfig.APPLICATION_ID,
VirtualAppManager.AIDL_SERVER_REMOTE_GUIDE_ACTIVITY
)
)
requireActivity().startActivity(intent)
}

View File

@ -1,6 +1,4 @@
<?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

@ -1,16 +0,0 @@
package com.gh.common.prioritychain
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
class VideoHandler(priority: Int, val scrollCalculatorHelper: ScrollCalculatorHelper): PriorityChainHandler(priority) {
init {
updateStatus(STATUS_VALID)
}
override fun onProcess(): Boolean {
scrollCalculatorHelper.enableAndPlayIfValid()
return true
}
}

View File

@ -2,15 +2,12 @@ package com.gh.common.provider
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import androidx.fragment.app.FragmentActivity
import com.alibaba.android.arouter.facade.annotation.Route
import com.gh.common.util.EntranceUtils
import com.gh.gamecenter.common.avoidcallback.Callback
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.core.provider.IEntranceUtilsProvider
import com.lightgame.utils.AppManager
@Route(path = RouteConsts.provider.entranceUtils, name = "EntranceUtils暴露服务")
class EntranceUtilsProviderImpl : IEntranceUtilsProvider {
@ -23,16 +20,11 @@ class EntranceUtilsProviderImpl : IEntranceUtilsProvider {
}
override fun jumpActivityWithCallback(context: Context, bundle: Bundle, callback: () -> Unit) {
if (context is FragmentActivity && !context.supportFragmentManager.isDestroyed) {
EntranceUtils.jumpActivity(context, null, bundle, object : Callback {
override fun onActivityResult(resultCode: Int, data: Intent?) {
callback()
}
})
} else {
EntranceUtils.jumpActivity(AppManager.getInstance().currentActivity(), bundle)
}
EntranceUtils.jumpActivity(context, null, bundle, object : Callback {
override fun onActivityResult(resultCode: Int, data: Intent?) {
callback()
}
})
}
override fun init(context: Context?) {

View File

@ -37,10 +37,10 @@ import com.gh.gamecenter.core.utils.*
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.PluginLocation
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.feature.view.DownloadButton
import com.gh.gamecenter.gamedetail.dialog.GamePermissionDialogFragment
import com.gh.gamecenter.manager.PackagesManager
import com.gh.gamecenter.feature.minigame.MiniGameItemHelper
import com.gh.gamecenter.teenagermode.TeenagerModeActivity
import com.gh.vspace.VHelper
import com.lightgame.download.DownloadConfig
@ -697,7 +697,7 @@ object DownloadItemUtils {
// 为 downloadButton 添加游戏实体,供点击的时候上报用
downloadBtn.putObject(gameEntity)
val gamePermissionDialogFragment = (context as? AppCompatActivity)?.supportFragmentManager?.findFragmentByTag(
val gamePermissionDialogFragment = (context as AppCompatActivity).supportFragmentManager.findFragmentByTag(
GamePermissionDialogFragment::class.java.name
) as GamePermissionDialogFragment?
gamePermissionDialogFragment?.dismissAllowingStateLoss()

View File

@ -105,14 +105,9 @@ public class EntranceUtils {
//TODO:添加FLAG_ACTIVITY_NEW_TASK会导致一跳转页面callback就被调用
//intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent1.putExtras(bundle);
if (context instanceof AppCompatActivity) {
AvoidOnResultManager.Companion.getInstance((AppCompatActivity) context)
.startForResult(intent1, callback);
} else {
// 不要回调,正常跳转
context.startActivity(intent1);
}
AvoidOnResultManager.Companion.getInstance((AppCompatActivity) context)
.startForResult(intent1, callback);
}
} else {
// 应用未在运行

View File

@ -7,7 +7,6 @@ import com.gh.gamecenter.common.utils.toObject
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.entity.SubjectEntity
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.manager.PackagesManager
import com.gh.gamecenter.retrofit.RetrofitManager
import com.halo.assistant.HaloApp
import io.reactivex.schedulers.Schedulers
@ -112,14 +111,6 @@ object GameSubstituteRepositoryHelper {
}
}
// 检查是否已安装该游戏 id
if (PackagesManager.getInstalledDataByGameId(game.id) != null) {
// 将该位置的游戏标记为需要替换
positionOfGameToBeReplacedList.add(index)
thisPositionNeedToBeReplaced = true
break
}
// 若此游戏所包含的 apk 没有已安装,那么再检查是否已安装有预设相关包名
if (!thisPositionNeedToBeReplaced) {
var relatedPackageList = arrayListOf<String>()

View File

@ -308,7 +308,7 @@ object GameUtils {
}
/**
* 是否默认以畅玩游戏的形式来处理
* 是否以畅玩游戏的形式来处理
*/
@JvmStatic
fun shouldPerformAsVGame(gameEntity: GameEntity): Boolean {

View File

@ -57,10 +57,6 @@ object HomeBottomBarHelper {
return BottomTab(name = "我的光环", jsCode = animationCode, iconSelector = R.drawable.selector_ic_user, link = LinkEntity(type = TYPE_MY_HALO))
}
fun isDefaultHomeBottomTabDataExist(): Boolean {
return SPUtils.getString(KEY_HOME_BOTTOM_TAB).isNotEmpty()
}
@JvmStatic
fun getDefaultHomeBottomTabData(): List<BottomTab> {
try {

View File

@ -90,7 +90,7 @@ object PackageChangeHelper : DefaultLifecycleObserver {
pendingPackageTriple = null
pendingGhId = null
PackageRepository.addInstalledGame(PackageRepository.packageFilterManager, packageName)
PackageRepository.addInstalledGame(packageName)
// 添加到额外的包名白名单,下次启动同时查询此包的安装情况
PackageHelper.updateAdditionalWhiteListPackageName(packageName = packageName, isAdd = true)

View File

@ -81,28 +81,23 @@ object PackageHelper {
// 评论黑名单包名列表,避免用户安装了 Xposed Installer 这样的工具,也能在包含该安装包的游戏详情页评论
private var _commentPackageNameBlackList = arrayListOf<String>()
val commentPackageNameBlackList: ArrayList<String>
get() = _commentPackageNameBlackList
val commentPackageNameBlackList: ArrayList<String> = _commentPackageNameBlackList
// 关闭下载的包列表
private var _downloadPackageNameBlackList = arrayListOf<String>()
val downloadPackageNameBlackList: ArrayList<String>
get() = _downloadPackageNameBlackList
val downloadPackageNameBlackList: ArrayList<String> = _downloadPackageNameBlackList
// 本地已安装的包去掉关闭下载的包后的列表
private var _validLocalPackageNameSet = hashSetOf<String>()
val validLocalPackageNameSet: HashSet<String>
get() = _validLocalPackageNameSet
val validLocalPackageNameSet: HashSet<String> = _validLocalPackageNameSet
// 游戏包名匹配列表
private var _relatedPackageList = arrayListOf<SettingsEntity.GameWithPackages>()
val relatedPackageList: ArrayList<SettingsEntity.GameWithPackages>
get() = _relatedPackageList
val relatedPackageList: ArrayList<SettingsEntity.GameWithPackages> = _relatedPackageList
// 接口控制的已安装应用列表获取开关状态 (UI 显示)
private var _installedPackageApiSwitchStatusLiveData = MutableLiveData<Boolean>()
val installedPackageApiSwitchStatusLiveData: LiveData<Boolean>
get() = _installedPackageApiSwitchStatusLiveData
val installedPackageApiSwitchStatusLiveData: LiveData<Boolean> = _installedPackageApiSwitchStatusLiveData
// 本地已安装包的列表
var localPackageNameSet = hashSetOf<String>()
@ -546,7 +541,6 @@ object PackageHelper {
Utils.log(TAG, "addInstalledButMissingPackages 需要请求接口获取的包数量为 ${installedPackageNameSet.size}")
PackageRepository.addInstalledGames(
packageFilterManager = PackageRepository.packageFilterManager,
pkgNameList = ArrayList(installedPackageNameSet),
updateInstallStatus = true
)

View File

@ -14,7 +14,6 @@ import android.os.Build;
import android.os.Bundle;
import android.os.PowerManager;
import android.text.TextUtils;
import android.util.AndroidException;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -223,19 +222,8 @@ public class PackageUtils {
if (metaDate != null) {
return metaDate.get(name);
}
} catch (Exception e) {
e.printStackTrace();
if (e instanceof AndroidException) {
// 有些设备会出现 DeadSystemException
SentryHelper.INSTANCE.onEvent(
"GET_META_DATA_ERROR",
"packageName",
packageName,
"exception_digest",
e.getLocalizedMessage()
);
}
} catch (NameNotFoundException e) {
// e.printStackTrace();
}
return null;
}
@ -639,19 +627,8 @@ public class PackageUtils {
try {
return HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).versionName;
} catch (Exception e) {
e.printStackTrace();
if (e instanceof AndroidException) {
// 有些设备会出现 DeadSystemException
SentryHelper.INSTANCE.onEvent(
"GET_VERSION_NAME_ERROR",
"packageName",
packageName,
"exception_digest",
e.getLocalizedMessage()
);
}
} catch (NameNotFoundException e) {
// do nothing
}
return null;
}
@ -663,18 +640,8 @@ public class PackageUtils {
try {
return HaloApp.getInstance().getApplication().getPackageManager().getPackageInfo(packageName,
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT).versionCode;
} catch (Exception e) {
e.printStackTrace();
if (e instanceof AndroidException) {
// 有些设备会出现 DeadSystemException
SentryHelper.INSTANCE.onEvent(
"GET_VERSION_CODE_ERROR",
"packageName",
packageName,
"exception_digest",
e.getLocalizedMessage()
);
}
} catch (NameNotFoundException e) {
// do nothing
}
return 0;
}
@ -687,18 +654,8 @@ public class PackageUtils {
try {
PackageManager packageManager = context.getApplicationContext().getPackageManager();
return packageManager.getApplicationIcon(packageName);
} catch (Exception e) {
e.printStackTrace();
if (e instanceof AndroidException) {
// 有些设备会出现 DeadSystemException
SentryHelper.INSTANCE.onEvent(
"GET_ICON_ERROR",
"packageName",
packageName,
"exception_digest",
e.getLocalizedMessage()
);
}
} catch (NameNotFoundException e) {
// do nothing
}
return null;
}
@ -749,19 +706,8 @@ public class PackageUtils {
jsonObject.put("version", packageInfo.versionName);
}
return jsonObject;
} catch (Exception e) {
} catch (JSONException | NameNotFoundException e) {
e.printStackTrace();
if (e instanceof AndroidException) {
// 有些设备会出现 DeadSystemException
SentryHelper.INSTANCE.onEvent(
"GET_APP_BASIC_INFO_BY_PACKAGE_NAME",
"packageName",
packageName,
"exception_digest",
e.getLocalizedMessage()
);
}
return jsonObject;
}
}

View File

@ -59,8 +59,8 @@ class GameDetailActivity : DownloadToolbarActivity() {
}
override fun getBusinessId(): Pair<String, String> {
val fragment = targetFragment as? GameDetailFragment?
return if (fragment?.arguments != null) {
val fragment = targetFragment as GameDetailFragment
return if (fragment.arguments != null) {
Pair(fragment.requireArguments().getString(EntranceConsts.KEY_GAMEID) ?: "", "")
} else {
super.getBusinessId()

View File

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

View File

@ -2,8 +2,8 @@ package com.gh.gamecenter.game.columncollection.detail
import android.content.Intent
import android.os.Bundle
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.activity.ToolBarActivity
import com.gh.gamecenter.R
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.utils.updateStatusBarColor
@ -34,8 +34,8 @@ class ColumnCollectionDetailActivity : ToolBarActivity() {
}
override fun getBusinessId(): Pair<String, String> {
val fragment = targetFragment as? ColumnCollectionDetailFragment?
return if (fragment?.arguments != null) {
val fragment = targetFragment as ColumnCollectionDetailFragment
return if (fragment.arguments != null) {
Pair(fragment.requireArguments().getString(EntranceConsts.KEY_COLLECTION_ID) ?: "", "")
} else {
super.getBusinessId()

View File

@ -36,8 +36,8 @@ class CommonCollectionDetailActivity : ToolBarActivity() {
}
override fun getBusinessId(): Pair<String, String> {
val fragment = targetFragment as? CommonCollectionDetailFragment?
return if (fragment?.arguments != null) {
val fragment = targetFragment as CommonCollectionDetailFragment
return if (fragment.arguments != null) {
Pair(
fragment.requireArguments().getString(EntranceConsts.KEY_COLLECTION_ID) ?: "",
fragment.requireArguments().getString(EntranceConsts.KEY_BLOCK_ID) ?: ""

View File

@ -36,8 +36,8 @@ class CustomCommonCollectionDetailActivity : ToolBarActivity() {
}
override fun getBusinessId(): Pair<String, String> {
val fragment = targetFragment as? CustomCommonCollectionDetailFragment?
return if (fragment?.arguments != null) {
val fragment = targetFragment as CustomCommonCollectionDetailFragment
return if (fragment.arguments != null) {
Pair(
fragment.requireArguments().getString(EntranceConsts.KEY_COLLECTION_ID) ?: "",
fragment.requireArguments().getString(EntranceConsts.KEY_BLOCK_ID) ?: ""

View File

@ -182,9 +182,7 @@ class AddGamesDialogFragment : BaseDialogFragment() {
return super.onBack()
}
private fun showGuidePopupWindow(): PopupWindow? {
if (!isAdded) return null
private fun showGuidePopupWindow(): PopupWindow {
val guideBinding = LayoutGameCollectionAddGamesGuideBinding.inflate(layoutInflater)
val popupWindow = BugFixedPopupWindow(
guideBinding.root,

View File

@ -7,8 +7,8 @@ import android.view.View
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.activity.ToolBarActivity
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.core.utils.DisplayUtils
import com.gh.gamecenter.common.exposure.ExposureSource
/**
* 游戏单详情
@ -30,8 +30,8 @@ class GameCollectionDetailActivity : ToolBarActivity() {
}
override fun getBusinessId(): Pair<String, String> {
val fragment = targetFragment as? GameCollectionDetailFragment?
return if (fragment?.arguments != null) {
val fragment = targetFragment as GameCollectionDetailFragment
return if (fragment.arguments != null) {
Pair(fragment.requireArguments().getString(EntranceConsts.KEY_GAME_COLLECTION_ID) ?: "", "")
} else {
super.getBusinessId()

View File

@ -149,6 +149,8 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
private var mShowConcernOnMenu = false
private var mSpecialDownloadDetailFragmentIsShowing = false
private val mFragmentsList = ArrayList<Fragment>()
private val mTabTitleList = ArrayList<String>()
private val mTabTypeList = ArrayList<String>() // tab 类型的列表,用于确定某个类型的 tab 在第几个位置
@ -165,7 +167,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
|| downloadEntity.status == DownloadStatus.redirected
) {
// 特殊下载弹窗
if (isSpecialDownloadDialogAvailable(downloadEntity) && !isSpecialDownloadDetailFragmentIsShowing()) {
if (isSpecialDownloadDialogAvailable() && !mSpecialDownloadDetailFragmentIsShowing) {
updateSpecialDownloadDialogIcon(true)
if (downloadEntity.status == DownloadStatus.add) {
@ -866,10 +868,8 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
showConcernIconAtBottomBarIfAvailable()
val downloadEntitySnapshot = DownloadManager.getInstance().getDownloadEntitySnapshot(mGameEntity)
if (isSpecialDownloadDialogAvailable(downloadEntitySnapshot)
&& downloadEntitySnapshot != null) {
if (isSpecialDownloadDialogAvailable()
&& DownloadManager.getInstance().getDownloadEntitySnapshot(mGameEntity) != null) {
updateSpecialDownloadDialogIcon(true)
}
@ -2562,15 +2562,12 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
* 2. 未获取到游戏详情数据
* 3. 当前游戏 APK 不为 1 个
* 4. 当前游戏类型不为畅玩
* 5. 当前游戏不是双下载时使用本地下载进行下载
*/
private fun isSpecialDownloadDialogAvailable(downloadEntity: DownloadEntity? = null): Boolean {
private fun isSpecialDownloadDialogAvailable(): Boolean {
if (Config.getNewApiSettingsEntity()?.install?.questionTip?.linkEntity == null) return false
if (mNewGameDetailEntity == null || mGameEntity == null) return false
if (mGameEntity?.getApk()?.size != 1) return false
if (downloadEntity?.asVGame() == true) return false
if (downloadEntity?.isSimulatorGame() == true) return false
if (downloadEntity?.isLocalDownloadInDualDownloadMode() == true) return false
if (GameUtils.shouldPerformAsVGame(mGameEntity!!)) return false
return true
}
@ -2588,6 +2585,7 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
if (fragment == null) {
if (!visibilityViewModel.specialDownloadVisibleLiveData.hasObservers()) {
visibilityViewModel.specialDownloadVisibleLiveData.observe(viewLifecycleOwner) {
mSpecialDownloadDetailFragmentIsShowing = it
updateSpecialDownloadDialogIcon(visible = !it)
}
}
@ -2603,10 +2601,6 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable {
}
}
private fun isSpecialDownloadDetailFragmentIsShowing(): Boolean {
return childFragmentManager.findFragmentByTag(TAG_SPECIAL_DOWNLOAD_DIALOG) != null
}
override fun scrollToTop() {
val fragment = mFragmentsList.safelyGetInRelease(mBodyBinding.gamedetailVp.currentItem)
if (fragment is IScrollable && fragment.isAdded) {

View File

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

View File

@ -17,7 +17,6 @@ import com.gh.common.iinterface.ISuperiorChain
import com.gh.common.prioritychain.CustomFloatingWindowHandler
import com.gh.common.prioritychain.PriorityChain
import com.gh.common.prioritychain.PullDownPushHandler
import com.gh.common.prioritychain.VideoHandler
import com.gh.common.util.DefaultSearchHintHelper
import com.gh.common.util.DialogUtils
import com.gh.common.util.DirectUtils
@ -469,10 +468,10 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
binding = FragmentCustomBinding.bind(mCachedView)
scrollCalculatorHelper = ScrollCalculatorHelper(binding.gameList, R.id.autoVideoView, 0, false)
buildPriorityChain()
scrollCalculatorHelper = ScrollCalculatorHelper(binding.gameList, R.id.autoVideoView, 0)
adapter = CustomPageAdapter(
viewModel,
viewLifecycleOwner,
@ -513,11 +512,9 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable {
private fun buildPriorityChain() {
val floatingWindowHandler = CustomFloatingWindowHandler(23)
val videoHandler = VideoHandler(24, scrollCalculatorHelper)
priorityChain.addHandler(pullDownPushHandler)
priorityChain.addHandler(floatingWindowHandler)
priorityChain.addHandler(videoHandler)
(parentFragment as? BaseTabWrapperFragment)?.addTabGuideHandlerIfExists(priorityChain)
viewModel.floatingWindows.observe(viewLifecycleOwner, EventObserver {

View File

@ -5,6 +5,7 @@ import android.os.Handler
import android.os.Looper
import android.view.View
import android.view.ViewGroup
import androidx.core.view.forEach
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.gh.gamecenter.common.constant.Constants
@ -14,28 +15,13 @@ import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.video.detail.CustomManager
import com.halo.assistant.HaloApp
class ScrollCalculatorHelper(
val mListRv: RecyclerView,
private val mPlayId: Int,
private val mRangeTop: Int,
private var isEnabled: Boolean = true
) {
class ScrollCalculatorHelper(val mListRv: RecyclerView, private val mPlayId: Int, private val mRangeTop: Int) {
private var mFirstVisible = -1
private var mLastVisible = 0
private var mRunnable: PlayRunnable? = null
private val mPlayHandler = Handler(Looper.getMainLooper())
var currentPlayer: AutomaticVideoView? = null
fun enableAndPlayIfValid() {
isEnabled = true
if (mListRv.isAttachedToWindow
&& mListRv.scrollState == RecyclerView.SCROLL_STATE_IDLE) {
playVideo(mListRv)
}
}
fun onScrollStateChanged(scrollState: Int) {
if (scrollState == RecyclerView.SCROLL_STATE_IDLE) {
playVideo(mListRv)
@ -94,7 +80,7 @@ class ScrollCalculatorHelper(
}
private fun playVideo(view: RecyclerView?) {
if (view == null || !view.isAttachedToWindow || !isEnabled) return
if (view == null) return
val layoutManager = view.layoutManager
var gsyBaseVideoPlayer: AutomaticVideoView
for (i in mFirstVisible until mLastVisible + 1) {

View File

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

View File

@ -130,24 +130,6 @@ object PackagesManager {
return null
}
/**
* 根据游戏 ID 获取已安装的信息
*
* @param gameId 游戏 Id
* @return 如果为空:未安装
*/
fun getInstalledDataByGameId(gameId: String?): GameInstall? {
if (TextUtils.isEmpty(gameId)) {
return null
}
for (gameInstall in mInstalledList) {
if (gameInstall.id == gameId) {
return gameInstall
}
}
return null
}
/**
* 判断包名是否可以更新

View File

@ -11,9 +11,11 @@ import com.gh.gamecenter.room.AppDatabase
import com.halo.assistant.HaloApp
import io.reactivex.schedulers.Schedulers
class PackageFilterManager {
object PackageFilterManager {
private var mPackageKey = "" // 用于下次获取包名-游戏信息的 key
private val mPendingPackageNameSet by lazy { hashSetOf<String>() } // 因遇到异常而等待下次操作更新的包名列表
private val mValidPackageNameSet by lazy { hashSetOf<String>() } // 已被收录的游戏包名列表
val packageKey: String
get() = mPackageKey
@ -32,7 +34,7 @@ class PackageFilterManager {
) {
if (appendOnly) {
// 添加因为异常而没能正常更新的包名列表
packageList.addAll(PackageRepository.mPendingPackageNameSet)
packageList.addAll(mPendingPackageNameSet)
}
RetrofitManager.getInstance()
@ -42,12 +44,12 @@ class PackageFilterManager {
.subscribe(object : BiResponse<PackageFilter>() {
override fun onSuccess(data: PackageFilter) {
mPackageKey = data.key
PackageRepository.mPendingPackageNameSet.clear()
mPendingPackageNameSet.clear()
val partialPackageList = arrayListOf<String>()
if (!appendOnly) {
PackageRepository.mValidPackageNameSet.clear()
mValidPackageNameSet.clear()
tryWithDefaultCatch {
AppDatabase.getInstance().packageFilterDao().deleteAllPackageName()
}
@ -61,13 +63,13 @@ class PackageFilterManager {
}
partialPackageList.add(packageName)
PackageRepository.mValidPackageNameSet.add(packageName)
mValidPackageNameSet.add(packageName)
}
if (appendOnly) {
callbackClosure?.invoke(ArrayList(partialPackageList))
} else {
callbackClosure?.invoke(ArrayList(PackageRepository.mValidPackageNameSet))
callbackClosure?.invoke(ArrayList(mValidPackageNameSet))
}
}
@ -75,7 +77,7 @@ class PackageFilterManager {
super.onFailure(exception)
if (appendOnly) {
PackageRepository.mPendingPackageNameSet.addAll(packageList)
mPendingPackageNameSet.addAll(packageList)
} else {
if (exception is retrofit2.HttpException && exception.code() == 403) {
// 403 代表 key 过期,需要重新获取
@ -89,13 +91,28 @@ class PackageFilterManager {
for (packageEntity in packageEntityList) {
// 依然为已安装状态才加入到有效包名列表中
if (PackageUtils.isInstalled(HaloApp.getInstance(), packageEntity.packageName)) {
PackageRepository.mValidPackageNameSet.add(packageEntity.packageName)
mValidPackageNameSet.add(packageEntity.packageName)
}
}
callbackClosure?.invoke(ArrayList(PackageRepository.mValidPackageNameSet))
callbackClosure?.invoke(ArrayList(mValidPackageNameSet))
}
}
})
}
/**
* 该包名是否有效 (即是否已被光环收录)
*/
fun isPackageValid(packageName: String): Boolean {
return mValidPackageNameSet.contains(packageName)
}
/**
* 是否存在因为接口异常而导致没有查询收录情况的包名列表
*/
fun hasPendingPackage(): Boolean {
return mPendingPackageNameSet.isEmpty()
}
}

View File

@ -6,6 +6,7 @@ import android.text.TextUtils
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.gh.common.filter.RegionSettingHelper
import com.gh.gamecenter.feature.utils.ApkActiveUtils
import com.gh.common.util.GameUtils
import com.gh.common.util.PackageUtils
import com.gh.gamecenter.R
@ -15,29 +16,19 @@ import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.retrofit.ObservableUtil
import com.gh.gamecenter.common.retrofit.Response
import com.gh.gamecenter.common.utils.secondOrNull
import com.gh.gamecenter.common.utils.toArrayList
import com.gh.gamecenter.common.utils.tryCatchInRelease
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.utils.SPUtils
import com.gh.gamecenter.entity.AppEntity
import com.gh.gamecenter.entity.GameUpdateEntity
import com.gh.gamecenter.entity.PackageGame
import com.gh.gamecenter.entity.*
import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.GameInstall
import com.gh.gamecenter.feature.utils.ApkActiveUtils
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.manager.PackagesManager
import com.gh.gamecenter.packagehelper.PackageRepository.gameInstalled
import com.gh.gamecenter.packagehelper.PackageRepository.gameUpdate
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.vspace.VHelper
import com.halo.assistant.HaloApp
import com.lightgame.utils.Utils
import io.reactivex.Single
import io.reactivex.SingleObserver
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import org.greenrobot.eventbus.EventBus
import org.json.JSONException
@ -83,10 +74,6 @@ object PackageRepository {
fun changeRecentVaPlayed() {
_recentVaPlayedChanged.postValue(Unit)
}
val packageFilterManager = PackageFilterManager()
var mPendingPackageNameSet = hashSetOf<String>() // 因遇到异常而等待下次操作更新的包名列表
var mValidPackageNameSet = hashSetOf<String>() // 已被收录的游戏包名列表
/**
* 预留方法,如果想手动初始化可以调用
@ -102,51 +89,18 @@ object PackageRepository {
if (gameUpdate.isNotEmpty()) gameUpdate.clear()
if (mInstalledPkgSet.isNotEmpty()) mInstalledPkgSet.clear()
Single.zip<Result<Any?>, Result<Any?>, Result<Any?>>(
Single.create { emitter ->
val list = PackageUtils.getAllPackageName(mApplication)
uploadAppList()
initFilterPackage(list) { filteredList ->
emitter.onSuccess(Result.success(null))
val list = PackageUtils.getAllPackageName(mApplication)
mInstalledPkgSet.addAll(filteredList)
notifyInstallPkgData()
loadInstalledGameDigestAndNotifyData(packageFilterManager.packageKey, filteredList)
}
uploadAppList()
initFilterPackage(list) { filteredList ->
mIsInitialisingData = false
},
Single.create { emitter ->
// 畅玩游戏更新
var allGames = VHelper.getAllVGameSnapshots()
if (allGames.isEmpty()) {
VHelper.refreshVGameSnapshot()
allGames = VHelper.getAllVGameSnapshots()
}
val allGamePkgNames = allGames.map { it.packageName }.toArrayList()
if (allGamePkgNames.isNotEmpty()) {
val packageFilterManager = PackageFilterManager()
updateFilterPackage(packageFilterManager, allGamePkgNames) {
emitter.onSuccess(Result.success(null))
loadInstalledGameDigestAndNotifyData(
packageKey = packageFilterManager.packageKey,
filteredList = allGamePkgNames,
isVGame = true
)
}
}
}
) { t1, t2 -> Result.success(null) }.subscribe(object : SingleObserver<Result<Any?>> {
override fun onSubscribe(d: Disposable) {
}
mInstalledPkgSet.addAll(filteredList)
notifyInstallPkgData()
override fun onSuccess(t: Result<Any?>) {
mIsInitialisingData = false
}
override fun onError(e: Throwable) {
}
})
loadInstalledGameDigestAndNotifyData(filteredList)
}
loadGhzsUpdate()
}
@ -159,15 +113,18 @@ object PackageRepository {
list: MutableList<String>,
callbackClosure: ((list: ArrayList<String>) -> Unit)? = null
) {
packageFilterManager.updateFilterPackages(list, false, callbackClosure)
PackageFilterManager.updateFilterPackages(list, false) {
callbackClosure?.invoke(it)
}
}
private fun updateFilterPackage(
packageFilterManager: PackageFilterManager,
list: MutableList<String>,
callbackClosure: ((list: ArrayList<String>) -> Unit)? = null
) {
packageFilterManager.updateFilterPackages(list, true, callbackClosure)
PackageFilterManager.updateFilterPackages(list, true) {
callbackClosure?.invoke(it)
}
}
/**
@ -178,8 +135,7 @@ object PackageRepository {
PackageUtils.getGhVersionName(),
PackageUtils.getGhVersionCode(),
HaloApp.getInstance().channel,
Build.VERSION.SDK_INT
)
Build.VERSION.SDK_INT)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Response<AppEntity>() {
@ -252,7 +208,6 @@ object PackageRepository {
*/
@SuppressLint("CheckResult")
private fun loadInstalledGameDigestAndNotifyData(
packageKey: String,
filteredList: ArrayList<String>,
isVGame: Boolean = false,
updateInstallStatus: Boolean = false
@ -267,7 +222,7 @@ object PackageRepository {
}, Any())
while (++page <= maxPageCount) {
var observable = mNewApi.getPackageGames(packageKey, page, PAGE_SIZE)
var observable = mNewApi.getPackageGames(PackageFilterManager.packageKey, page, PAGE_SIZE)
.subscribeOn(Schedulers.io())
observable.subscribe(object : BiResponse<List<PackageGame>>() {
@ -283,8 +238,7 @@ object PackageRepository {
}
for (game in validGames) {
val shouldNotifyChanges =
validateGameAndPostChanges(gh_id, game, pkgName, isVGame, updateInstallStatus)
val shouldNotifyChanges = validateGameAndPostChanges(gh_id, game, pkgName, isVGame, updateInstallStatus)
if (!isNotifyUpdate && shouldNotifyChanges) {
isNotifyUpdate = true
}
@ -305,13 +259,11 @@ object PackageRepository {
/**
* 验证游戏并且更新数据
*/
private fun validateGameAndPostChanges(
ghId: Any?,
game: GameEntity,
pkgName: String,
isVGame: Boolean,
updateInstallStatus: Boolean
): Boolean {
private fun validateGameAndPostChanges(ghId: Any?,
game: GameEntity,
pkgName: String,
isVGame: Boolean,
updateInstallStatus: Boolean): Boolean {
if (ghId == null || ghId == game.id) {
gameInstalled.add(GameInstall.transformGameInstall(game, pkgName, isVGame))
mInstalledGameList.add(game)
@ -320,8 +272,7 @@ object PackageRepository {
addCurrentlyInstalledVersionIfValid(game)
if (updateInstallStatus) {
EventBus.getDefault()
.post(EBPackage(EBPackage.TYPE_INSTALLED, pkgName, game.getApk().firstOrNull()?.version))
EventBus.getDefault().post(EBPackage(EBPackage.TYPE_INSTALLED, pkgName, game.getApk().firstOrNull()?.version))
}
if (isCanUpdate || isCanPluggable) {
@ -405,8 +356,7 @@ object PackageRepository {
) {
// 使用了镜像的游戏;插件化关闭的游戏;无需插件化
if (game.shouldUseMirrorInfo()
|| apk.plugin == "close"
) {
|| apk.plugin == "close") {
return false
}
@ -466,11 +416,8 @@ object PackageRepository {
* @param pkgName 已安装的游戏包名
* @param cachedGameEntity 缓存的游戏实体,若存在免去再请求接口的过程
*/
fun addInstalledGame(
packageFilterManager: PackageFilterManager,
pkgName: String,
cachedGameEntity: GameEntity? = null
) {
fun addInstalledGame(pkgName: String,
cachedGameEntity: GameEntity? = null) {
mInstalledPkgSet.add(pkgName)
notifyInstallPkgData()
@ -481,8 +428,7 @@ object PackageRepository {
game = cachedGameEntity,
pkgName = pkgName,
isVGame = false,
updateInstallStatus = false
)
updateInstallStatus = false)
if (containsUpdate) {
notifyGameUpdateData()
@ -490,9 +436,8 @@ object PackageRepository {
} else {
val list = arrayListOf(pkgName)
updateFilterPackage(packageFilterManager, list) {
updateFilterPackage(list) {
loadInstalledGameDigestAndNotifyData(
packageKey = packageFilterManager.packageKey,
filteredList = list,
updateInstallStatus = false
)
@ -508,11 +453,9 @@ object PackageRepository {
* @param isVGame 是否为畅玩游戏
* @param updateInstallStatus 是否更新安装状态
*/
fun addInstalledGames(
packageFilterManager: PackageFilterManager,
pkgNameList: ArrayList<String>,
isVGame: Boolean = false,
updateInstallStatus: Boolean = false,
fun addInstalledGames(pkgNameList: ArrayList<String>,
isVGame: Boolean = false,
updateInstallStatus: Boolean = false,
) {
// 畅玩游戏不添加至本地的已安装包名列表中
if (!isVGame) {
@ -522,9 +465,8 @@ object PackageRepository {
}
notifyInstallPkgData()
updateFilterPackage(packageFilterManager, pkgNameList) {
updateFilterPackage(pkgNameList) {
loadInstalledGameDigestAndNotifyData(
packageKey = packageFilterManager.packageKey,
filteredList = pkgNameList,
isVGame = isVGame,
updateInstallStatus = updateInstallStatus
@ -584,13 +526,6 @@ object PackageRepository {
changeRecentVaPlayed()
}
/**
* 是否存在因为接口异常而导致没有查询收录情况的包名列表
*/
fun hasPendingPackage(): Boolean {
return mPendingPackageNameSet.isEmpty()
}
private fun notifyGameInstallData() {
PackagesManager.initGameInstall(ArrayList(gameInstalled))
gameInstalledLiveData.postValue(ArrayList(gameInstalled))

View File

@ -63,13 +63,7 @@ class PackageViewModel(
* @param cachedGameEntity 缓存的游戏实体
*/
fun addInstalledGame(pkgName: String?, cachedGameEntity: GameEntity? = null) {
if (!TextUtils.isEmpty(pkgName)) {
mRepository.addInstalledGame(
mRepository.packageFilterManager,
pkgName!!,
cachedGameEntity
)
}
if (!TextUtils.isEmpty(pkgName)) mRepository.addInstalledGame(pkgName!!, cachedGameEntity)
}
/**
@ -87,7 +81,9 @@ class PackageViewModel(
// 未同意获取已安装应用权限时不进行数据初始化
if (!PackageHelper.isGetInstalledPackagesAgreed()) return
if (mRepository.gameInstalled.size == 0 || mRepository.hasPendingPackage()) {
if (mRepository.gameInstalled.size == 0
|| PackageFilterManager.hasPendingPackage()
) {
PackageHelper.initPackageRelatedData();
}
}

View File

@ -699,8 +699,6 @@ class HaloPersonalFragment : BaseLazyFragment() {
} catch (e: Exception) {
} as? ITestCase)?.apply {
addInstallExternalGameButton(mStubBinding.otherItems)
addInstallPluginButton(mStubBinding.otherItems)
addInstallPlugin32Button(mStubBinding.otherItems)
}
}

View File

@ -16,12 +16,11 @@ import com.gh.gamecenter.common.utils.ImageUtils
import com.gh.gamecenter.common.utils.dip2px
import com.gh.gamecenter.databinding.PieceBottomTabBinding
import com.gh.gamecenter.entity.BottomTab
import com.gh.gamecenter.feature.utils.SentryHelper
/**
* 底部Tab 基类
*/
abstract class BaseBottomTabFragment<T : ViewBinding> : ToolbarFragment() {
abstract class BaseBottomTabFragment<T: ViewBinding>: ToolbarFragment() {
protected var mViewPager: ViewPager2? = null
protected var mBottomTabContainer: LinearLayout? = null
@ -45,7 +44,6 @@ abstract class BaseBottomTabFragment<T : ViewBinding> : ToolbarFragment() {
protected fun initBottomTab(bottomTabList: List<BottomTab>) {
mBottomTabBindingList.clear()
mBottomTabContainer?.run {
visibility = View.VISIBLE
removeAllViews()
bottomTabList.forEachIndexed { index, bottomTab ->
addView(
@ -63,13 +61,6 @@ abstract class BaseBottomTabFragment<T : ViewBinding> : ToolbarFragment() {
.apply {
tabTv.text = bottomTab.name
if (!TextUtils.isEmpty(bottomTab.jsCode)) {
tabLottie.setFailureListener {
SentryHelper.onEvent(
SENTRY_ID_BOTTOM_TAB_LOTTIE_LOAD_FAILED,
BOTTOM_TAB_ID, bottomTab.id,
BOTTOM_TAB_NAME, bottomTab.name
)
}
tabLottie.setAnimationFromJson(bottomTab.jsCode, bottomTab.id + bottomTab.name)
}
if (bottomTab.iconSelector != 0) {
@ -131,13 +122,6 @@ abstract class BaseBottomTabFragment<T : ViewBinding> : ToolbarFragment() {
protected open fun onPageSelected(position: Int) {
checkIndex(position)
}
protected open fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
protected open fun onPageScrollStateChanged(state: Int) {}
companion object {
private const val SENTRY_ID_BOTTOM_TAB_LOTTIE_LOAD_FAILED = "bottom_tab_lottie_load_failed"
private const val BOTTOM_TAB_ID = "bottom_tab_id"
private const val BOTTOM_TAB_NAME = "bottom_tab_name"
}
}

View File

@ -13,8 +13,6 @@ import androidx.constraintlayout.widget.ConstraintSet
import androidx.core.text.color
import androidx.core.view.doOnNextLayout
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.ethanhua.skeleton.Skeleton
import com.ethanhua.skeleton.SkeletonScreen
import com.gh.common.iinterface.ISuperiorChain
import com.gh.common.prioritychain.BottomTabGuideHandler
import com.gh.common.prioritychain.GlobalPriorityChainHelper
@ -50,8 +48,6 @@ class MainWrapperFragment : BaseBottomTabFragment<PieceBottomTabBinding>(), OnBa
private var mBottomTabGuideHandler: BottomTabGuideHandler? = null
private var mBottomTabGuidePopupWindow: PopupWindow? = null
private var mSkeletonScreen: SkeletonScreen? = null
override fun getLayoutId(): Int = 0
override fun getInflatedLayout(): View = mBinding.root
override fun provideAdapter(): FragmentStateAdapter = mAdapter
@ -67,13 +63,10 @@ class MainWrapperFragment : BaseBottomTabFragment<PieceBottomTabBinding>(), OnBa
super.onCreate(savedInstanceState)
DisplayUtils.transparentStatusBar(requireActivity())
initSkeleton()
mBinding.viewShadow.visibility = if (mIsDarkModeOn) View.GONE else View.VISIBLE
buildPriorityChain()
mViewModel?.bottomTabListLiveData?.observe(this) {
mSkeletonScreen?.hide()
mBottomTabList.clear()
mBottomTabList.addAll(it)
mViewPager?.offscreenPageLimit = it.size
@ -91,18 +84,6 @@ class MainWrapperFragment : BaseBottomTabFragment<PieceBottomTabBinding>(), OnBa
mPriorityChain.addHandler(mBottomTabGuideHandler!!)
}
private fun initSkeleton() {
mSkeletonScreen = Skeleton.bind(mBinding.skeleton)
.shimmer(true)
.angle(Constants.SHIMMER_ANGLE)
.color(R.color.ui_skeleton_highlight)
.duration(Constants.SHIMMER_DURATION)
.maskWidth(Constants.MASK_WIDTH)
.gradientCenterColorWidth(Constants.GRADIENT_CENTER_COLOR_WIDTH)
.load(R.layout.fragment_main_skeleton)
.show()
}
private fun showBottomTabGuideIfExists() {
val guidePosition = mBottomTabList.indexOfFirst { it.guide != null }
if (guidePosition != -1) {

View File

@ -3,10 +3,10 @@ package com.gh.gamecenter.wrapper
import android.annotation.SuppressLint
import androidx.lifecycle.MutableLiveData
import com.gh.common.util.HomeBottomBarHelper
import com.gh.common.util.HomeBottomBarHelper.isDefaultHomeBottomTabDataExist
import com.gh.common.util.ViewPagerFragmentHelper
import com.gh.gamecenter.common.entity.LaunchRedirect
import com.gh.gamecenter.common.retrofit.BiResponse
import com.gh.gamecenter.common.utils.singleToMain
import com.gh.gamecenter.core.utils.GsonUtils
import com.gh.gamecenter.core.utils.SingletonHolder
import com.gh.gamecenter.entity.BottomTab
@ -17,7 +17,6 @@ import com.gh.gamecenter.retrofit.RetrofitManager
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.launch
@ -135,13 +134,7 @@ class MainWrapperRepository {
@SuppressLint("CheckResult")
fun getDataUnion() {
// 若历史 tab 数据存在,优先使用作为占位
if (isDefaultHomeBottomTabDataExist()) {
processBottomTabData(emptyList())
} else {
// 若 timeout 后数据未加载完成,则即便还没回调 onFailure 也生成两个底部 tab
emitDefaultTabDataAfterTimeout()
}
processBottomTabData(emptyList())
mNewApi.dataUnion
.subscribeOn(Schedulers.io())
.subscribe(object : BiResponse<DataUnionEntity>() {
@ -239,15 +232,6 @@ class MainWrapperRepository {
multiTabNavLiveData.postValue(multiTabNav)
}
private fun emitDefaultTabDataAfterTimeout() {
CoroutineScope(SupervisorJob()).launch {
delay(3000)
if (!mMainDataIsLoaded) {
processBottomTabData(emptyList())
}
}
}
companion object : SingletonHolder<MainWrapperRepository>({ MainWrapperRepository() })
}

View File

@ -58,7 +58,6 @@ import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.feature.exposure.ExposureEvent
import com.gh.gamecenter.feature.exposure.time.TimeUtil
import com.gh.gamecenter.feature.game.GameItemViewHolder
import com.gh.gamecenter.feature.utils.SentryHelper
import com.gh.gamecenter.gamecollection.square.GameCollectionSquareFragment
import com.gh.gamecenter.home.custom.CustomPageFragment
import com.gh.gamecenter.home.video.ScrollCalculatorHelper
@ -90,18 +89,7 @@ import kotlin.math.roundToInt
* @see Style
*/
class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbarTab, ISmartRefresh, ISuperiorChain {
private val mBinding by lazy {
try {
FragmentSearchToolbarTabWrapperBinding.inflate(layoutInflater)
} catch (e: Exception) {
SentryHelper.onEvent("VIEW_BINDING_BIND_ERROR",
"digest", e.localizedMessage,
"gid", HaloApp.getInstance().gid
)
// 玄学,重试一次,该闪退闪退
FragmentSearchToolbarTabWrapperBinding.inflate(layoutInflater)
}
}
private val mBinding by lazy { FragmentSearchToolbarTabWrapperBinding.inflate(layoutInflater) }
private val mViewModel: SearchToolbarTabWrapperViewModel by lazy {
viewModelProviderFromParent(
SearchToolbarTabWrapperViewModel.Factory(mMultiTabNavId, mNoTabLinkEntity?.link ?: ""),

View File

@ -14,11 +14,9 @@ import android.text.TextUtils;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import com.blankj.utilcode.util.ThreadUtils;
import com.gh.download.DownloadManager;
import com.gh.gamecenter.SplashScreenActivity;
import com.gh.gamecenter.common.base.GlobalActivityManager;
import com.gh.gamecenter.core.AppExecutor;
import com.gh.ndownload.suspendwindow.NDownloadDrawOverlayPermissionWindowController;
import com.gh.ndownload.suspendwindow.NDownloadSuspendWindowController;
import com.gh.ndownload.suspendwindow.utils.NDownloadSuspendWindowHelper;
@ -284,14 +282,6 @@ public class NDownloadService extends Service {
}
private void showDownloadSuspendWindowIfNeeded(DownloadEntity entry) {
if (ThreadUtils.isMainThread()) {
showDownloadSuspendWindowIfNeededInner(entry);
} else {
AppExecutor.getUiExecutor().execute(() -> showDownloadSuspendWindowIfNeededInner(entry));
}
}
private void showDownloadSuspendWindowIfNeededInner(DownloadEntity entry) {
if (!NDownloadSuspendWindowHelper.shouldSkipDownloadEntity(getApplicationContext(), entry)) {
if (NDownloadSuspendWindowHelper.canDrawOverLayer(getApplicationContext())) {// 已开启悬浮窗权限,直接显示悬浮窗
showDownloadSuspendWindow();

View File

@ -4,7 +4,6 @@ import android.app.Activity
import android.app.Application
import android.app.Application.ActivityLifecycleCallbacks
import android.os.Bundle
import androidx.core.view.ViewCompat
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.SensorsBridge
import com.gh.gamecenter.common.utils.asVGame
@ -46,9 +45,7 @@ class NDownloadDrawOverlayPermissionWindowController(val application: Applicatio
}
fun show(activity: Activity) {
val decorView = activity.window.decorView
val isAttachedToWindow = ViewCompat.isAttachedToWindow(decorView)
if (isStarted || !isAttachedToWindow) return
if (isStarted) return
isStarted = true
currentActivityRef = WeakReference(activity)
onAttachToUi(activity)
@ -127,10 +124,10 @@ class NDownloadDrawOverlayPermissionWindowController(val application: Applicatio
SensorsBridge.trackDownloadSuspendedWindowGuideShow(
gameId = downloadEntity.gameId,
gameName = downloadEntity.name,
gameSchemaType = if (downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位",
gameSchemeType = if(downloadEntity.getMetaExtra(Constants.KEY_BIT) == "32") "32位" else "64位",
gameType = downloadEntity.categoryChinese,
downloadStatus = downloadEntity.getMetaExtra(Constants.DOWNLOAD_STATUS_IN_CHINESE),
downloadType = if (downloadEntity.asVGame()) "畅玩下载" else "本地下载"
downloadType = if(downloadEntity.asVGame()) "畅玩下载" else "本地下载"
)
}
}

View File

@ -33,7 +33,7 @@ import org.greenrobot.eventbus.ThreadMode
* 下载悬浮窗-控制器
*/
class NDownloadSuspendWindowController(private val application: Application) :
NDownloadSuspendIconLayout.OnDragCallback, Application.ActivityLifecycleCallbacks,
NDownloadSuspendIconLayout.OnDragListener, Application.ActivityLifecycleCallbacks,
PackageInstaller.OnInstallListener, NDownloadSuspendIconView.OnIconClickListener {
private var isStarted = false
@ -75,24 +75,22 @@ class NDownloadSuspendWindowController(private val application: Application) :
downloadCount = 0
currentDownloadEntity = null
onDetachFromUi()
NDataChanger.deleteObserver(downloadObserver)
PackageInstaller.unregisterOnInstallListener(this)
EventBus.getDefault().unregister(this)
application.unregisterActivityLifecycleCallbacks(this)
onDetachFromUi()
isStarted = false
}
private fun onAttachToUi() {
closeWindow.attach()
iconWindow.attach()
iconWindow.setOnDragCallback(this)
iconWindow.setOnDragListener(this)
iconWindow.setOnIconClickListener(this)
}
private fun onDetachFromUi() {
iconWindow.setOnDragCallback(null)
iconWindow.setOnIconClickListener(null)
closeWindow.detach()
iconWindow.detach()
}

View File

@ -12,7 +12,6 @@ import com.gh.download.DownloadManager
import com.gh.gamecenter.common.constant.Constants
import com.gh.gamecenter.common.utils.asVGame
import com.gh.gamecenter.common.utils.getExtension
import com.gh.gamecenter.common.utils.isLocalDownloadInDualDownloadMode
import com.gh.gamecenter.common.utils.isSimulatorDownload
import com.gh.gamecenter.common.utils.isSimulatorGame
import com.gh.gamecenter.core.utils.SPUtils
@ -185,7 +184,6 @@ object NDownloadSuspendWindowHelper {
|| downloadEntity.isPluggable
|| downloadEntity.isSimulatorDownload()
|| downloadEntity.isSimulatorGame()
|| downloadEntity.isLocalDownloadInDualDownloadMode()
@JvmStatic
fun isDrawOverlayPermissionWindowShown(): Boolean =

View File

@ -26,7 +26,7 @@ class NDownloadSuspendIconLayout @JvmOverloads constructor(
ViewConfiguration.get(context).scaledTouchSlop
}
private var onDragCallback: OnDragCallback? = null
private var onDragListener: OnDragListener? = null
val icon = NDownloadSuspendIconView(context).also {
it.clipChildren = false
@ -39,12 +39,12 @@ class NDownloadSuspendIconLayout @JvmOverloads constructor(
addView(it, LayoutParams(size, size))
}
fun setOnDragCallback(onDragCallback: OnDragCallback?) {
this.onDragCallback = onDragCallback
fun setOnDragListener(onDragListener: OnDragListener) {
this.onDragListener = onDragListener
}
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
val onDragCallback = this.onDragCallback
val onDragListener = this.onDragListener
?: return super.onInterceptTouchEvent(ev)
if (ev.action == MotionEvent.ACTION_DOWN) {
@ -66,7 +66,7 @@ class NDownloadSuspendIconLayout @JvmOverloads constructor(
val dragging = xDiff > touchSlop || yDiff > touchSlop
if (dragging) {
isDragging = true
onDragCallback.onDragStart(this)
onDragListener.onDragStart(this)
return true
}
return super.onInterceptTouchEvent(ev)
@ -81,7 +81,7 @@ class NDownloadSuspendIconLayout @JvmOverloads constructor(
@SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(ev: MotionEvent): Boolean {
val onDragListener = this.onDragCallback
val onDragListener = this.onDragListener
?: return super.onInterceptTouchEvent(ev)
when(ev.action) {
@ -93,7 +93,7 @@ class NDownloadSuspendIconLayout @JvmOverloads constructor(
return super.onTouchEvent(ev)
}
interface OnDragCallback {
interface OnDragListener {
fun onDragStart(v: View)

View File

@ -109,7 +109,7 @@ class NDownloadSuspendIconView @JvmOverloads constructor(
addView(it, layoutParams)
}
fun setOnIconClickListener(listener: OnIconClickListener?) {
fun setOnIconClickListener(listener: OnIconClickListener) {
this.onIconClickListener = listener
}

View File

@ -56,13 +56,6 @@ class NDownloadSuspendCloseWindow(context: Context, suspend: Boolean = true) :
it.visibility = View.GONE
}
override fun onDetach() {
popupAnimator.removeListener(hiddenListener)
popupAnimator.removeListener(shownListener)
popupAnimator.cancel()
root.visibility = View.GONE
}
override fun onViewCreated(view: NDownloadSuspendCloseLayout) {
view.apply {
popupAnimator.addUpdateListener { value ->

View File

@ -19,7 +19,7 @@ import com.gh.ndownload.suspendwindow.view.NDownloadSuspendIconView
*/
class NDownloadSuspendIconWindow(context: Context, suspend: Boolean = true, private val draggable: Boolean = true) :
NDownloadSuspendWindow<NDownloadSuspendIconLayout>(context, suspend),
NDownloadSuspendIconLayout.OnDragCallback {
NDownloadSuspendIconLayout.OnDragListener {
companion object {
private const val TYPE_DRAGGING = 0
@ -40,7 +40,7 @@ class NDownloadSuspendIconWindow(context: Context, suspend: Boolean = true, priv
/**
* 图标拖动回调事件
*/
private var onDragCallback: NDownloadSuspendIconLayout.OnDragCallback? = null
private var onDragListener: NDownloadSuspendIconLayout.OnDragListener? = null
/**
* 手指松开拖动的悬浮图标时,自动吸附到屏幕侧边的动画
@ -67,30 +67,20 @@ class NDownloadSuspendIconWindow(context: Context, suspend: Boolean = true, priv
get() = root.getLocationOnScreen(screenLocation)
.let { screenLocation[1] - layoutParams.y }
fun setOnDragCallback(onDragCallback: NDownloadSuspendIconLayout.OnDragCallback?) {
this.onDragCallback = onDragCallback
fun setOnDragListener(onDragListener: NDownloadSuspendIconLayout.OnDragListener?) {
this.onDragListener = onDragListener
}
override fun onAttach() {
if (draggable) {
root.post(initRunnable)
root.setOnDragCallback(this)
}
}
override fun onDetach() {
if (draggable) {
root.removeCallbacks(initRunnable)
root.setOnDragCallback(null)
}
edgeAnimator.removeAllUpdateListeners()
edgeAnimator.removeAllListeners()
override fun detach() {
super.detach()
root.removeCallbacks(initRunnable)
edgeAnimator.cancel()
}
@SuppressLint("InflateParams")
override fun onCreateView(context: Context): NDownloadSuspendIconLayout =
NDownloadSuspendIconLayout(context).also {
if (draggable) it.setOnDragListener(this)
it.clipChildren = false
it.clipToPadding = false
}
@ -106,6 +96,7 @@ class NDownloadSuspendIconWindow(context: Context, suspend: Boolean = true, priv
override fun onViewCreated(view: NDownloadSuspendIconLayout) {
super.onViewCreated(view)
view.setBackgroundResource(R.drawable.shape_download_suspend_icon_idle_right)
if (draggable) view.post(initRunnable)
}
override fun onConfigurationChanged(configuration: Configuration) {
@ -144,7 +135,7 @@ class NDownloadSuspendIconWindow(context: Context, suspend: Boolean = true, priv
root.icon.setDownloadIconUrl(url)
}
fun setOnIconClickListener(listener: NDownloadSuspendIconView.OnIconClickListener?) {
fun setOnIconClickListener(listener: NDownloadSuspendIconView.OnIconClickListener) {
root.icon.setOnIconClickListener(listener)
}
@ -212,16 +203,16 @@ class NDownloadSuspendIconWindow(context: Context, suspend: Boolean = true, priv
override fun onDragStart(v: View) {
setIconLayoutStyleByType(TYPE_DRAGGING)
onDragCallback?.onDragStart(v)
onDragListener?.onDragStart(v)
}
override fun onDragMove(v: View, x: Float, y: Float) {
moveToPosition(v, x, y)
onDragCallback?.onDragMove(v, x, y)
onDragListener?.onDragMove(v, x, y)
}
override fun onDragEnd(v: View, x: Float, y: Float) {
animateToEdge(v, x, y)
onDragCallback?.onDragEnd(v, x, y)
onDragListener?.onDragEnd(v, x, y)
}
}

View File

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

View File

@ -8,6 +8,4 @@ public interface ITestCase {
void addInstallExternalGameButton(@NonNull ViewGroup viewParent);
void addInstallPluginButton(@NonNull ViewGroup viewParent);
void addInstallPlugin32Button(@NonNull ViewGroup viewParent);
}

View File

@ -56,7 +56,6 @@ import com.gh.gamecenter.history.HistoryActivity
import com.gh.gamecenter.login.user.UserManager
import com.gh.gamecenter.manager.PackagesManager
import com.gh.gamecenter.mygame.MyGameActivity
import com.gh.gamecenter.packagehelper.PackageFilterManager
import com.gh.gamecenter.packagehelper.PackageRepository
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.subject.SubjectActivity
@ -1998,7 +1997,7 @@ object VHelper {
validInstalledPackageList.add(packageName)
}
}
PackageRepository.addInstalledGames(PackageFilterManager(), validInstalledPackageList, true)
PackageRepository.addInstalledGames(validInstalledPackageList, true)
}
/**
@ -2278,13 +2277,6 @@ object VHelper {
val token = UserManager.getInstance().token
val userName = UserManager.getInstance().userInfoEntity?.name
val userAvatar = UserManager.getInstance().userInfoEntity?.icon
if (token == null) {
SentryHelper.onEvent("LAUNCH_SUCCESS_BUT_TOKEN_EMPTY", "gid", HaloApp.getInstance().gid)
Utils.log(LOG_TAG, "登录成功,但 token 为空")
return@runOnIoThread
}
Utils.log(
LOG_TAG,
"登录成功,插入用户信息:token=${token},userName=${userName}, uri=${va.getUriAuthorizationString()}"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 554 B

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="20dp" />
<solid android:color="@color/ui_skeleton_frame" />
</shape>

View File

@ -142,14 +142,7 @@
android:focusable="true"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<FrameLayout
android:id="@+id/skeleton"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.gh.gamecenter.common.view.MaterializedConstraintLayout>

View File

@ -1,316 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/b"
android:orientation="vertical">
<com.gh.gamecenter.common.view.StatusBarView
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:paddingStart="16dp"
android:paddingEnd="16dp">
<View
android:id="@+id/sb"
android:layout_width="0dp"
android:layout_height="32dp"
android:layout_marginEnd="16dp"
android:background="@drawable/bg_skeleton_radius_40"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/ic1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/ic1"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="16dp"
android:background="@drawable/bg_skeleton_radius_4"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/ic2"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/ic2"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:background="@drawable/bg_skeleton_radius_4"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="28dp"
android:gravity="bottom"
android:paddingTop="8dp">
<View
android:layout_width="40dp"
android:layout_height="20dp"
android:layout_marginStart="16dp"
android:background="@drawable/bg_skeleton_radius_4" />
<View
android:layout_width="32dp"
android:layout_height="16dp"
android:layout_marginStart="24dp"
android:background="@drawable/bg_skeleton_radius_4" />
<View
android:layout_width="64dp"
android:layout_height="16dp"
android:layout_marginStart="24dp"
android:background="@drawable/bg_skeleton_radius_4" />
<View
android:layout_width="32dp"
android:layout_height="16dp"
android:layout_marginStart="24dp"
android:background="@drawable/bg_skeleton_radius_4" />
<View
android:layout_width="32dp"
android:layout_height="16dp"
android:layout_marginStart="24dp"
android:background="@drawable/bg_skeleton_radius_4" />
<View
android:layout_width="32dp"
android:layout_height="16dp"
android:layout_marginStart="24dp"
android:background="@drawable/bg_skeleton_radius_4" />
<View
android:layout_width="64dp"
android:layout_height="16dp"
android:layout_marginStart="24dp"
android:background="@drawable/bg_skeleton_radius_4" />
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="29dp"
android:layout_marginTop="7dp"
android:src="@drawable/ic_home_tab_indicator_skeleton" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp">
<View
android:id="@+id/square"
android:layout_width="0dp"
android:layout_height="140dp"
android:layout_marginEnd="8dp"
android:background="@drawable/bg_skeleton_radius_10"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/rect1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/rect1"
android:layout_width="0dp"
android:layout_height="66dp"
android:background="@drawable/bg_skeleton_radius_10"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@id/square"
app:layout_constraintTop_toTopOf="@id/square" />
<View
android:id="@+id/rect2"
android:layout_width="0dp"
android:layout_height="66dp"
android:layout_marginTop="8dp"
android:background="@drawable/bg_skeleton_radius_10"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="@id/rect1"
app:layout_constraintTop_toBottomOf="@id/rect1" />
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="87dp"
android:orientation="horizontal"
android:paddingHorizontal="18dp"
android:paddingVertical="16dp">
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/bg_skeleton_radius_8" />
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="26dp"
android:layout_weight="1"
android:background="@drawable/bg_skeleton_radius_8" />
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="26dp"
android:layout_weight="1"
android:background="@drawable/bg_skeleton_radius_8" />
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="26dp"
android:layout_weight="1"
android:background="@drawable/bg_skeleton_radius_8" />
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="26dp"
android:layout_weight="1"
android:background="@drawable/bg_skeleton_radius_8" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="16dp"
android:paddingBottom="16dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="18dp">
<View
android:layout_width="54dp"
android:layout_height="18dp"
android:layout_marginStart="16dp"
android:background="@drawable/bg_skeleton_radius_4" />
<View
android:layout_width="32dp"
android:layout_height="12dp"
android:layout_alignParentEnd="true"
android:layout_marginEnd="16dp"
android:background="@drawable/bg_skeleton_radius_4" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="53dp"
android:background="@drawable/bg_skeleton_radius_4" />
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:orientation="horizontal">
<include layout="@layout/fragment_main_skeleton_item_simple_game" />
<include layout="@layout/fragment_main_skeleton_item_simple_game" />
<include layout="@layout/fragment_main_skeleton_item_simple_game" />
<include layout="@layout/fragment_main_skeleton_item_simple_game" />
<include layout="@layout/fragment_main_skeleton_item_simple_game" />
<include layout="@layout/fragment_main_skeleton_item_simple_game" />
<include layout="@layout/fragment_main_skeleton_item_simple_game" />
</LinearLayout>
</HorizontalScrollView>
</RelativeLayout>
</LinearLayout>
<include layout="@layout/fragment_main_skeleton_item_game" />
<include layout="@layout/fragment_main_skeleton_item_game" />
<include layout="@layout/fragment_main_skeleton_item_game" />
</LinearLayout>
<LinearLayout
android:id="@+id/b"
android:layout_width="match_parent"
android:layout_height="54dp"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<include
layout="@layout/fragment_main_skeleton_item_bottom_tab"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<include
layout="@layout/fragment_main_skeleton_item_bottom_tab"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<include
layout="@layout/fragment_main_skeleton_item_bottom_tab"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<include
layout="@layout/fragment_main_skeleton_item_bottom_tab"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<include
layout="@layout/fragment_main_skeleton_item_bottom_tab"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
</RelativeLayout>

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<View
android:layout_width="22dp"
android:layout_height="22dp"
android:background="@drawable/bg_skeleton_radius_4" />
<View
android:layout_width="22dp"
android:layout_height="10dp"
android:layout_marginTop="6dp"
android:background="@drawable/bg_skeleton_radius_4" />
</LinearLayout>
</LinearLayout>

View File

@ -1,47 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingTop="8dp"
android:paddingRight="16dp"
android:paddingBottom="8dp">
<View
android:layout_width="64dp"
android:layout_height="64dp"
android:background="@drawable/bg_skeleton_radius_14" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:layout_marginTop="4dp"
android:layout_weight="1"
android:orientation="vertical">
<View
android:layout_width="72dp"
android:layout_height="16dp"
android:background="@drawable/bg_skeleton_radius_4" />
<View
android:layout_width="160dp"
android:layout_height="12dp"
android:layout_marginTop="8dp"
android:background="@drawable/bg_skeleton_radius_4" />
<View
android:layout_width="32dp"
android:layout_height="12dp"
android:layout_marginTop="8dp"
android:background="@drawable/bg_skeleton_radius_4" />
</LinearLayout>
<View
android:layout_width="56dp"
android:layout_height="28dp"
android:layout_gravity="center_vertical"
android:background="@drawable/bg_skeleton_radius_999" />
</LinearLayout>

View File

@ -1,49 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="80dp"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical">
<View
android:layout_width="28dp"
android:layout_height="11dp"
android:background="@drawable/bg_skeleton_radius_4" />
<View
android:layout_width="44dp"
android:layout_height="11dp"
android:layout_marginTop="8dp"
android:background="@drawable/bg_skeleton_radius_4"/>
<View
android:layout_width="5dp"
android:layout_height="5dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:background="@drawable/bg_skeleton_radius_40"/>
<View
android:layout_width="64dp"
android:layout_height="64dp"
android:background="@drawable/bg_skeleton_radius_14" />
<View
android:layout_width="64dp"
android:layout_height="16dp"
android:layout_marginTop="8dp"
android:background="@drawable/bg_skeleton_radius_4" />
<View
android:layout_width="56dp"
android:layout_height="28dp"
android:layout_marginTop="12dp"
android:background="@drawable/bg_skeleton_radius_40" />
</LinearLayout>
</LinearLayout>

View File

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

View File

@ -7,8 +7,8 @@ ext {
targetSdkVersion = 30
// application info (每个大版本之间的 versionCode 增加 20)
versionCode = 1095
versionName = "5.37.5"
versionCode = 1110
versionName = "5.38.0"
applicationId = "com.gh.gamecenter"
applicationIdGat = "com.gh.gamecenter.intl"

View File

@ -1,5 +1,5 @@
ext {
vaCompileSdkVersion = 34
vaCompileSdkVersion = 33
vaMinSdkVersion = 21
vaTargetSdkVersion = 28
}

View File

@ -323,11 +323,14 @@ class HelpAndFeedbackFragment : BaseLazyFragment() {
mPopupWindow = null
}
}
popupWindow.width = mBinding.helpCenterTv.width
popupWindow.isTouchable = true
popupWindow.isFocusable = true
popupWindow.animationStyle = 0
popupWindow.showAsDropDown(mBinding.helpCenterTv, 0, 0)
binding.root.layoutParams = (binding.root.layoutParams as MarginLayoutParams).apply {
leftMargin = 16F.dip2px()
rightMargin = 16F.dip2px()
}
}
private fun toggleHighlightedView(targetView: View, highlightIt: Boolean) {

View File

@ -4,6 +4,7 @@ import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.DiffUtil
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.gh.gamecenter.common.utils.safelyGetInRelease
import com.gh.gamecenter.core.AppExecutor
/**
* 支持diff刷新的FragmentStateAdapter
@ -63,7 +64,7 @@ abstract class BaseDiffFragmentStateAdapter<T>(fragment: Fragment) : FragmentSta
abstract fun createFragment(data: T?, position: Int): Fragment?
override fun getItemId(position: Int): Long {
if (mDataList.size <= position) {
if (mDataList.size < position) {
return 0L
}
return mDataList[position].hashCode().toLong()

View File

@ -14,11 +14,11 @@ import android.view.ViewGroup
import androidx.annotation.RequiresApi
import androidx.fragment.app.FragmentActivity
import com.alibaba.android.arouter.launcher.ARouter
import com.gh.gamecenter.common.base.fragment.BaseDialogFragment
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.common.databinding.DialogAlertDefaultBinding
import com.gh.gamecenter.core.AppExecutor
import com.gh.gamecenter.core.provider.IAppProvider
import com.lightgame.dialog.BaseDialogFragment
@RequiresApi(Build.VERSION_CODES.R)
class ManageExternalStoragePermissionDialogFragment : BaseDialogFragment() {

View File

@ -26,7 +26,7 @@ object SensorsBridge {
private const val KEY_LAST_PAGE_BUSINESS_ID = "last_page_business_id"
private const val KEY_DOWNLOAD_STATUS = "download_status"
private const val KEY_DOWNLOAD_TYPE = "download_type"
private const val KEY_GAME_SCHEMA_TYPE = "game_schema_type"
private const val KEY_GAME_SCHEME_TYPE = "game_scheme_type"
private const val KEY_GAME_TYPE = "game_type"
const val KEY_POSITION = "position"
const val KEY_TAB_CONTENT = "tab_content"
@ -4070,7 +4070,7 @@ object SensorsBridge {
* 触发时机:当下载悬浮窗引导图展示时触发上报
* @param gameId 游戏ID
* @param gameName 游戏名称
* @param gameSchemaType 游戏架构类型64位/32位
* @param gameSchemeType 游戏架构类型64位/32位
* @param downloadStatus 游戏下载状态
* @param gameType 游戏的类型:单机、网游等
* @param downloadType 实际下载方式:本地下载/畅玩下载
@ -4079,7 +4079,7 @@ object SensorsBridge {
fun trackDownloadSuspendedWindowGuideShow(
gameId: String,
gameName: String,
gameSchemaType: String,
gameSchemeType: String,
downloadStatus: String,
gameType: String,
downloadType: String
@ -4087,7 +4087,7 @@ object SensorsBridge {
val json = json {
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
KEY_GAME_SCHEMA_TYPE to gameSchemaType
KEY_GAME_SCHEME_TYPE to gameSchemeType
KEY_DOWNLOAD_STATUS to downloadStatus
KEY_GAME_TYPE to gameType
KEY_DOWNLOAD_TYPE to downloadType
@ -4126,7 +4126,7 @@ object SensorsBridge {
* @param source 来源:游戏下载\重启APP
* @param downloadType 所上报游戏的实际下载方式:本地下载/畅玩下载
* @param downloadStatus 所上报游戏下载状态
* @param gameSchemaType 所上报游戏架构类型64位/32位
* @param gameSchemeType 所上报游戏架构类型64位/32位
* @param gameType 游戏的类型:单机、网游等
* @param gameId 游戏ID
* @param gameName 游戏名称
@ -4135,7 +4135,7 @@ object SensorsBridge {
source: String,
downloadType: String,
downloadStatus: String,
gameSchemaType: String,
gameSchemeType: String,
gameType: String,
gameId: String,
gameName: String
@ -4144,7 +4144,7 @@ object SensorsBridge {
KEY_SOURCE to source
KEY_DOWNLOAD_TYPE to downloadType
KEY_DOWNLOAD_STATUS to downloadStatus
KEY_GAME_SCHEMA_TYPE to gameSchemaType
KEY_GAME_SCHEME_TYPE to gameSchemeType
KEY_GAME_TYPE to gameType
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
@ -4159,7 +4159,7 @@ object SensorsBridge {
* @param source 来源:游戏下载\重启APP
* @param downloadType 所上报游戏的实际下载方式:本地下载/畅玩下载
* @param downloadStatus 所上报游戏下载状态
* @param gameSchemaType 所上报游戏架构类型64位/32位
* @param gameSchemeType 所上报游戏架构类型64位/32位
* @param gameType 游戏的类型:单机、网游等
* @param gameId 游戏ID
* @param gameName 游戏名称
@ -4168,7 +4168,7 @@ object SensorsBridge {
source: String,
downloadType: String,
downloadStatus: String,
gameSchemaType: String,
gameSchemeType: String,
gameType: String,
gameId: String,
gameName: String
@ -4177,7 +4177,7 @@ object SensorsBridge {
KEY_SOURCE to source
KEY_DOWNLOAD_TYPE to downloadType
KEY_DOWNLOAD_STATUS to downloadStatus
KEY_GAME_SCHEMA_TYPE to gameSchemaType
KEY_GAME_SCHEME_TYPE to gameSchemeType
KEY_GAME_TYPE to gameType
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
@ -4191,7 +4191,7 @@ object SensorsBridge {
* 触发时机:触发自动下载提示条展示时上报
* @param downloadType 所上报游戏的实际下载方式:本地下载/畅玩下载
* @param downloadStatus 所上报游戏下载状态
* @param gameSchemaType 所上报游戏架构类型64位/32位
* @param gameSchemeType 所上报游戏架构类型64位/32位
* @param gameType 游戏的类型:单机、网游等
* @param gameId 游戏ID
* @param gameName 游戏名称
@ -4199,7 +4199,7 @@ object SensorsBridge {
fun trackAutomaticInstallationPromptBarShow(
downloadType: String,
downloadStatus: String,
gameSchemaType: String,
gameSchemeType: String,
gameType: String,
gameId: String,
gameName: String
@ -4207,7 +4207,7 @@ object SensorsBridge {
val json = json {
KEY_DOWNLOAD_TYPE to downloadType
KEY_DOWNLOAD_STATUS to downloadStatus
KEY_GAME_SCHEMA_TYPE to gameSchemaType
KEY_GAME_SCHEME_TYPE to gameSchemeType
KEY_GAME_TYPE to gameType
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
@ -4221,7 +4221,7 @@ object SensorsBridge {
* 触发时机:触发自动下载提示条点击时上报
* @param downloadType 所上报游戏的实际下载方式:本地下载/畅玩下载
* @param downloadStatus 所上报游戏下载状态
* @param gameSchemaType 所上报游戏架构类型64位/32位
* @param gameSchemeType 所上报游戏架构类型64位/32位
* @param gameType 游戏的类型:单机、网游等
* @param gameId 游戏ID
* @param gameName 游戏名称
@ -4229,7 +4229,7 @@ object SensorsBridge {
fun trackAutomaticInstallationPromptBarClick(
downloadType: String,
downloadStatus: String,
gameSchemaType: String,
gameSchemeType: String,
gameType: String,
gameId: String,
gameName: String
@ -4237,7 +4237,7 @@ object SensorsBridge {
val json = json {
KEY_DOWNLOAD_TYPE to downloadType
KEY_DOWNLOAD_STATUS to downloadStatus
KEY_GAME_SCHEMA_TYPE to gameSchemaType
KEY_GAME_SCHEME_TYPE to gameSchemeType
KEY_GAME_TYPE to gameType
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
@ -4251,7 +4251,7 @@ object SensorsBridge {
* 触发时机:下载组件展示时上报
* @param gameId 游戏ID
* @param gameName 游戏名称
* @param gameSchemaType 游戏架构类型64位/32位
* @param gameSchemeType 游戏架构类型64位/32位
* @param downloadStatus 所上报游戏下载状态
* @param gameType 游戏的类型:单机、网游等
* @param downloadType 所上报游戏的实际下载方式:本地下载/畅玩下载
@ -4259,7 +4259,7 @@ object SensorsBridge {
fun trackDownloadComponentsShow(
gameId: String,
gameName: String,
gameSchemaType: String,
gameSchemeType: String,
downloadStatus: String,
gameType: String,
downloadType: String,
@ -4267,7 +4267,7 @@ object SensorsBridge {
val json = json {
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
KEY_GAME_SCHEMA_TYPE to gameSchemaType
KEY_GAME_SCHEME_TYPE to gameSchemeType
KEY_DOWNLOAD_STATUS to downloadStatus
KEY_GAME_TYPE to gameType
KEY_DOWNLOAD_TYPE to downloadType
@ -4281,7 +4281,7 @@ object SensorsBridge {
* 触发时机:下载组件点击时上报
* @param gameId 游戏ID
* @param gameName 游戏名称
* @param gameSchemaType 游戏架构类型64位/32位
* @param gameSchemeType 游戏架构类型64位/32位
* @param downloadStatus 所上报游戏下载状态
* @param gameType 游戏的类型:单机、网游等
* @param downloadType 所上报游戏的实际下载方式:本地下载/畅玩下载
@ -4291,7 +4291,7 @@ object SensorsBridge {
fun trackDownloadComponentsContentClick(
gameId: String,
gameName: String,
gameSchemaType: String,
gameSchemeType: String,
downloadStatus: String,
gameType: String,
downloadType: String,
@ -4301,7 +4301,7 @@ object SensorsBridge {
val json = json {
KEY_GAME_ID to gameId
KEY_GAME_NAME to gameName
KEY_GAME_SCHEMA_TYPE to gameSchemaType
KEY_GAME_SCHEME_TYPE to gameSchemeType
KEY_DOWNLOAD_STATUS to downloadStatus
KEY_GAME_TYPE to gameType
KEY_DOWNLOAD_TYPE to downloadType

View File

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

View File

@ -62,14 +62,16 @@ class AboutFragment : ToolbarFragment() {
ARouter.getInstance().build(RouteConsts.provider.updateManager).navigation() as? IUpdateManagerProvider
updateManager?.checkUpdate(requireActivity(), true) // 检查更新
var clickCount = 0
mBinding.aboutGhIcon.setOnClickListener {
if (clickCount == 5) {
mBinding.aboutGhIcon.setOnClickListener(null)
mBinding.deviceContent.visibility = View.VISIBLE
mBinding.deviceContent.text.toString().copyTextAndToast("复制成功!")
} else {
clickCount++
if (PackageFlavorHelper.IS_TEST_FLAVOR) {
var clickCount = 0
mBinding.aboutGhIcon.setOnClickListener {
if (clickCount == 5) {
mBinding.aboutGhIcon.setOnClickListener(null)
mBinding.deviceContent.visibility = View.VISIBLE
mBinding.deviceContent.text.toString().copyTextAndToast("复制成功!")
} else {
clickCount++
}
}
}

View File

@ -131,7 +131,6 @@ class ComposeAboutActivity : ComposeBaseActivity() {
}
},
onPress = {
if (deviceContent.isNotEmpty()) return@detectTapGestures
if (clickCount == 5) {
val sb = StringBuilder()
val meta = MetaUtil.getMeta()

View File

@ -49,18 +49,6 @@ android {
publish {
dimension "env"
}
tea {
dimension "env"
}
kuaishou {
dimension "env"
}
gdt {
dimension "env"
}
sm {
dimension "env"
}
}
}

View File

@ -3,9 +3,15 @@ package com.gh.gamecenter.va
import android.app.Application
import android.content.Context
import android.content.res.Configuration
import com.alibaba.android.arouter.launcher.ARouter
import com.gh.gamecenter.common.constant.RouteConsts
import com.gh.gamecenter.core.iinterface.IApplication
import com.gh.gamecenter.core.provider.IAppProvider
import com.gh.gamecenter.core.provider.ISentryProvider
import com.google.auto.service.AutoService
import com.lg.vspace.common.CommonApp
import com.lody.virtual.client.core.VirtualCore
import com.lody.virtual.client.core.VirtualCore.VirtualInitializer
@AutoService(IApplication::class)
class HaloApp : IApplication {
@ -17,6 +23,20 @@ class HaloApp : IApplication {
}
override fun onCreate(application: Application) {
VirtualCore.get().initialize(object : VirtualInitializer() {
override fun onServerProcess() {
(ARouter.getInstance().build(RouteConsts.provider.app)
.navigation() as? IAppProvider)?.let { appProvider ->
(ARouter.getInstance().build(RouteConsts.provider.sentry).navigation() as? ISentryProvider)?.init(
application,
appProvider.getChannel(),
appProvider.getFlavor(),
appProvider.getAppVersion()
)
}
}
})
commonApp.onCreate(application)
}

2
vasdk

Submodule vasdk updated: ff118306e4...e64cec2695