diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f5ae376fc5..39b99920ae 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -865,10 +865,6 @@ - - - - diff --git a/app/src/main/java/com/gh/common/constant/Config.java b/app/src/main/java/com/gh/common/constant/Config.java index 2639b42f2f..5f58dd1b5a 100644 --- a/app/src/main/java/com/gh/common/constant/Config.java +++ b/app/src/main/java/com/gh/common/constant/Config.java @@ -114,8 +114,6 @@ public class Config { if (!TextUtils.isEmpty(json)) { mSettingsEntity = GsonUtils.fromJson(json, SettingsEntity.class); } - - mSettingsEntity.setGameSmooth("off"); } catch (Exception e) { e.printStackTrace(); } diff --git a/app/src/main/java/com/gh/common/databind/BindingAdapters.java b/app/src/main/java/com/gh/common/databind/BindingAdapters.java index b38ed479a1..700c0f8402 100644 --- a/app/src/main/java/com/gh/common/databind/BindingAdapters.java +++ b/app/src/main/java/com/gh/common/databind/BindingAdapters.java @@ -287,19 +287,11 @@ public class BindingAdapters { }); break; case RESERVED: - if ("download".equals(gameEntity.getReserveStatus())) { - ReservationHelper.showDeleteReservationDialog(progressBar.getContext(), () -> { - ReservationHelper.deleteReservation(gameEntity, () -> { - updateReservation(progressBar, gameEntity); - }); + ReservationHelper.showCancelReservationDialog(progressBar.getContext(),gameEntity, () -> { + ReservationHelper.cancelReservation(gameEntity, () -> { + updateReservation(progressBar, gameEntity); }); - } else { - ReservationHelper.showCancelReservationDialog(progressBar.getContext(),gameEntity, () -> { - ReservationHelper.cancelReservation(gameEntity, () -> { - updateReservation(progressBar, gameEntity); - }); - }); - } + }); break; case H5_GAME: LinkEntity linkEntity = gameEntity.getH5Link(); diff --git a/app/src/main/java/com/gh/common/exposure/ExposureListener.kt b/app/src/main/java/com/gh/common/exposure/ExposureListener.kt index 7d8dc605df..d71f1342f7 100644 --- a/app/src/main/java/com/gh/common/exposure/ExposureListener.kt +++ b/app/src/main/java/com/gh/common/exposure/ExposureListener.kt @@ -31,6 +31,7 @@ class ExposureListener(var fragment: Fragment, var exposable: IExposable) : Recy override fun onFragmentPaused(fm: FragmentManager, f: Fragment) { if (fragment == f) { visibleState?.let { commitExposure(it) } + visibleState?.let { commitWXCPMExposure(it) } throttleBus.clear() } } diff --git a/app/src/main/java/com/gh/common/iinterface/ISmartRefreshContent.kt b/app/src/main/java/com/gh/common/iinterface/ISmartRefreshContent.kt index d8c91f6ebe..3ca103ee0a 100644 --- a/app/src/main/java/com/gh/common/iinterface/ISmartRefreshContent.kt +++ b/app/src/main/java/com/gh/common/iinterface/ISmartRefreshContent.kt @@ -1,12 +1,9 @@ package com.gh.common.iinterface -interface ISmartRefreshContent { - /** - * 启用/关闭 页面滑动 - * @param isScrollEnabled 是否启用 - */ - fun setScrollEnabled(isScrollEnabled: Boolean) +import com.scwang.smartrefresh.layout.api.RefreshLayout +import com.scwang.smartrefresh.layout.constant.RefreshState +interface ISmartRefreshContent { fun onRefresh() /** @@ -14,4 +11,6 @@ interface ISmartRefreshContent { * @param isSwipeRefreshEnabled 是否启用 */ fun setSwipeRefreshEnabled(isSwipeRefreshEnabled: Boolean) + + fun onStateChanged(refreshLayout: RefreshLayout, oldState: RefreshState, newState: RefreshState) } \ No newline at end of file diff --git a/app/src/main/java/com/gh/common/provider/DownloadButtonClickedProviderImpl.kt b/app/src/main/java/com/gh/common/provider/DownloadButtonClickedProviderImpl.kt index 2ad28ceaa6..de5040b6ba 100644 --- a/app/src/main/java/com/gh/common/provider/DownloadButtonClickedProviderImpl.kt +++ b/app/src/main/java/com/gh/common/provider/DownloadButtonClickedProviderImpl.kt @@ -112,6 +112,12 @@ class DownloadButtonClickedProviderImpl : IDownloadButtonClickedProvider { "本地下载" } + // 小游戏的启动不需要上报下载点击事件 + // @see https://jira.shanqu.cc/browse/GHZSCY-7013 + if (boundedObject is GameEntity && boundedObject.isMiniGame()) { + return + } + // 上报神策点击事件 val customPageKV = customPageTrackData?.toKV() ?: arrayOf() SensorsBridge.trackEventWithExposureSource( diff --git a/app/src/main/java/com/gh/common/simulator/SimulatorGameManager.kt b/app/src/main/java/com/gh/common/simulator/SimulatorGameManager.kt index 60193d0c24..09295a3ebc 100644 --- a/app/src/main/java/com/gh/common/simulator/SimulatorGameManager.kt +++ b/app/src/main/java/com/gh/common/simulator/SimulatorGameManager.kt @@ -4,6 +4,8 @@ import android.annotation.SuppressLint import android.content.ActivityNotFoundException import android.content.Context import android.content.Intent +import android.database.sqlite.SQLiteDiskIOException +import android.database.sqlite.SQLiteException import android.graphics.Bitmap import android.net.Uri import android.text.TextUtils @@ -284,7 +286,11 @@ object SimulatorGameManager { entity.isRecentlyPlayed = it.id == gameId simulatorGameRecordList.add(entity) } - simulatorGameDao.addSimulatorGameList(simulatorGameRecordList) + try { + simulatorGameDao.addSimulatorGameList(simulatorGameRecordList) + } catch (e: SQLiteException) { + e.printStackTrace() + } } }) } diff --git a/app/src/main/java/com/gh/common/util/DataUtils.java b/app/src/main/java/com/gh/common/util/DataUtils.java index 1fc8a399d2..b9f96d3246 100644 --- a/app/src/main/java/com/gh/common/util/DataUtils.java +++ b/app/src/main/java/com/gh/common/util/DataUtils.java @@ -16,6 +16,7 @@ import com.gh.gamecenter.common.constant.Constants; import com.gh.gamecenter.common.constant.RouteConsts; import com.gh.gamecenter.common.exposure.meta.MetaUtil; import com.gh.gamecenter.common.retrofit.BiResponse; +import com.gh.gamecenter.common.utils.SensorsBridge; import com.gh.gamecenter.core.AppExecutor; import com.gh.gamecenter.core.provider.ISentryProvider; import com.gh.gamecenter.core.utils.GsonUtils; @@ -39,6 +40,11 @@ import io.reactivex.schedulers.Schedulers; */ public class DataUtils { + // 神策 OAID 是否已绑定 + private static boolean isSensorOAIDBounded = false; + // 原始的 OAID 是否已成功获取 + private static boolean originalOAIDIsReceived = false; + private DataUtils() { throw new IllegalStateException("Utility class"); } @@ -65,7 +71,6 @@ public class DataUtils { // 默认用 APP 级已存储的 GID 来使用,不使用外部 GID String savedGid = SPUtils.getString(Constants.GID); if (!TextUtils.isEmpty(savedGid)) { - HaloApp.getInstance().setGid(savedGid); onGidReceived(savedGid); } else { GidHelper.getInstance().registerDevice(HaloApp.getInstance().getApplication(), new GidCallback() { @@ -89,6 +94,8 @@ public class DataUtils { } private static void onGidReceived(String gid) { + bindValidOaidToSensor(false); + HaloApp.getInstance().setGid(gid); // 更新广告配置 AdDelegateHelper.INSTANCE.requestAdConfig(false, "", null); @@ -111,6 +118,35 @@ public class DataUtils { }); } + /** + * 为神策绑定有效的 OAID + */ + public static void bindValidOaidToSensor(boolean fromOaidResult) { + if (isSensorOAIDBounded) return; + + String oaid = HaloApp.getInstance().getOAID(); + + // 来自于 oaid 获取回调,或者说原始 oaid 已经获取成功 + if (fromOaidResult || originalOAIDIsReceived) { + originalOAIDIsReceived = true; + // 遇到异常的 OAID + if (Constants.INVALID_OAID_1.equals(oaid) + || Constants.INVALID_OAID_2.equals(oaid) + || Constants.INVALID_OAID_3.equals(oaid) + || TextUtils.isEmpty(oaid)) { + // 若 gid 不为空,那么整合 gid 作为 oaid https://jira.shanqu.cc/browse/GHZSCY-7004 + if (HaloApp.getInstance().getGid() != null) { + oaid = "GID" + HaloApp.getInstance().getGid(); + SensorsBridge.INSTANCE.setOAID(oaid); + isSensorOAIDBounded = true; + } + } else { + SensorsBridge.INSTANCE.setOAID(oaid); + isSensorOAIDBounded = true; + } + } + } + /** * 获取应用 gid 绑定的实名信息 */ diff --git a/app/src/main/java/com/gh/common/util/DownloadItemUtils.kt b/app/src/main/java/com/gh/common/util/DownloadItemUtils.kt index ddcd190d6c..9123c40e82 100644 --- a/app/src/main/java/com/gh/common/util/DownloadItemUtils.kt +++ b/app/src/main/java/com/gh/common/util/DownloadItemUtils.kt @@ -839,34 +839,25 @@ object DownloadItemUtils { } else { allStateClickCallback?.onCallback() clickCallback?.onCallback() - if ("download" == gameEntity.reserveStatus) { - ReservationHelper.showDeleteReservationDialog(context) { - ReservationHelper.deleteReservation(gameEntity) { - adapter?.notifyItemChanged(position) - refreshCallback?.onCallback() - } + ReservationHelper.showCancelReservationDialog(context, gameEntity, { + NewFlatLogUtils.logMyGameCancelReserveDialogClick( + "确定取消", + gameEntity.id, + gameEntity.name ?: "" + ) + ReservationHelper.cancelReservation(gameEntity) { + adapter?.notifyItemChanged(position) + refreshCallback?.onCallback() } - } else { - ReservationHelper.showCancelReservationDialog(context, gameEntity,{ + }, object : CancelListener { + override fun onCancel() { NewFlatLogUtils.logMyGameCancelReserveDialogClick( - "确定取消", + "关闭弹窗", gameEntity.id, gameEntity.name ?: "" ) - ReservationHelper.cancelReservation(gameEntity) { - adapter?.notifyItemChanged(position) - refreshCallback?.onCallback() - } - }, object : CancelListener { - override fun onCancel() { - NewFlatLogUtils.logMyGameCancelReserveDialogClick( - "关闭弹窗", - gameEntity.id, - gameEntity.name ?: "" - ) - } - }) - } + } + }) } } return diff --git a/app/src/main/java/com/gh/common/util/PackageInstaller.kt b/app/src/main/java/com/gh/common/util/PackageInstaller.kt index 6de598abef..6fa1321a95 100644 --- a/app/src/main/java/com/gh/common/util/PackageInstaller.kt +++ b/app/src/main/java/com/gh/common/util/PackageInstaller.kt @@ -18,7 +18,6 @@ import com.gh.gamecenter.common.constant.Constants import com.gh.gamecenter.common.utils.* import com.gh.gamecenter.core.utils.MD5Utils import com.gh.gamecenter.core.utils.ToastUtils -import com.gh.gamecenter.install.InstallService import com.gh.vspace.VHelper import com.halo.assistant.HaloApp import com.lightgame.download.DownloadEntity @@ -194,12 +193,6 @@ object PackageInstaller { private fun install(context: Context, pkgPath: String, pkgName: String?) { HaloApp.put(Constants.LAST_INSTALL_GAME, pkgPath) - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU && Build.MANUFACTURER.lowercase().contains("xiaomi")) { - val foregroundServiceIntent = Intent(context, InstallService::class.java) - foregroundServiceIntent.putExtra(InstallService.KEY_SERVICE_ACTION, InstallService.START_FOREGROUND) - context.startForegroundService(foregroundServiceIntent) - } - val installIntent = getInstallIntent(context, pkgPath) context.startActivity(installIntent) diff --git a/app/src/main/java/com/gh/common/util/PackageUtils.java b/app/src/main/java/com/gh/common/util/PackageUtils.java index b68bbd2ccd..976da13a9a 100644 --- a/app/src/main/java/com/gh/common/util/PackageUtils.java +++ b/app/src/main/java/com/gh/common/util/PackageUtils.java @@ -14,7 +14,6 @@ import android.os.Build; import android.os.Bundle; import android.os.PowerManager; import android.text.TextUtils; -import android.util.AndroidException; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -29,9 +28,9 @@ import com.gh.gamecenter.BuildConfig; import com.gh.gamecenter.common.constant.Constants; import com.gh.gamecenter.common.utils.ExtensionsKt; import com.gh.gamecenter.core.utils.MD5Utils; +import com.gh.gamecenter.entity.GameUpdateEntity; import com.gh.gamecenter.feature.entity.ApkEntity; import com.gh.gamecenter.feature.entity.GameEntity; -import com.gh.gamecenter.entity.GameUpdateEntity; import com.gh.gamecenter.feature.utils.SentryHelper; import com.gh.gamecenter.manager.PackagesManager; import com.gh.vspace.VHelper; @@ -643,6 +642,19 @@ public class PackageUtils { return 0; } + /* + * 获取应用的名称 + */ + public static CharSequence getNameByPackageName(Context context, String packageName) { + try { + PackageManager packageManager = context.getApplicationContext().getPackageManager(); + return packageManager.getApplicationLabel(packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA)); + } catch (Exception e) { + e.printStackTrace(); + } + return ""; + } + /* * 获取应用的 icon diff --git a/app/src/main/java/com/gh/common/util/ReservationHelper.kt b/app/src/main/java/com/gh/common/util/ReservationHelper.kt index 9e26532884..8deefc2e60 100644 --- a/app/src/main/java/com/gh/common/util/ReservationHelper.kt +++ b/app/src/main/java/com/gh/common/util/ReservationHelper.kt @@ -29,53 +29,31 @@ import okhttp3.ResponseBody object ReservationHelper { - @JvmStatic - fun deleteReservation(game: GameEntity, refreshCallback: EmptyCallback) { - deleteOrCancelReservation(game, true, refreshCallback) - } - - @JvmStatic - fun cancelReservation(game: GameEntity, refreshCallback: EmptyCallback) { - deleteOrCancelReservation(game, false, refreshCallback) - } - @SuppressLint("CheckResult") - private fun deleteOrCancelReservation( + @JvmStatic + fun cancelReservation( game: GameEntity, - deleteReservation: Boolean, refreshCallback: EmptyCallback ) { - val retrofit = RetrofitManager.getInstance() - val single = if (deleteReservation) { - retrofit.newApi - .deleteGameReservation( - game.id, - getReserveRequestBody(game, context = HaloApp.getInstance().application) - ) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - } else { - retrofit.newApi - .cancelGameReservation( - game.id, - getReserveRequestBody(game, context = HaloApp.getInstance().application) - ) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - } + retrofit.newApi + .cancelGameReservation( + game.id, + getReserveRequestBody(game, context = HaloApp.getInstance().application) + ) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : BiResponse() { + override fun onSuccess(data: ResponseBody) { + ReservationRepository.removeReservationFromMemoryAndRefresh(game.id) + refreshCallback.onCallback() + } - single.subscribe(object : BiResponse() { - override fun onSuccess(data: ResponseBody) { - ReservationRepository.removeReservationFromMemoryAndRefresh(game.id) - refreshCallback.onCallback() - } - - override fun onFailure(exception: Exception) { - Utils.toast(HaloApp.getInstance().application, exception.message) - exception.printStackTrace() - } - }) + override fun onFailure(exception: Exception) { + Utils.toast(HaloApp.getInstance().application, exception.message) + exception.printStackTrace() + } + }) } @JvmStatic @@ -146,21 +124,6 @@ object ReservationHelper { }) } - @JvmStatic - fun showDeleteReservationDialog(context: Context, emptyCallback: EmptyCallback) { - DialogUtils.showCancelOrDeleteReservationDialog( - context, - "删除预约", - "游戏已上线,你可以删除此预约记录,确定删除吗?", - "确定删除", - "暂不删除", object : ConfirmListener { - override fun onConfirm() { - emptyCallback.onCallback() - } - }, null - ) - } - @JvmStatic fun showCancelReservationDialog(context: Context, game: GameEntity?, emptyCallback: EmptyCallback) { showCancelReservationDialog(context, game, emptyCallback, null) diff --git a/app/src/main/java/com/gh/download/simple/DownloadMessageHandler.kt b/app/src/main/java/com/gh/download/simple/DownloadMessageHandler.kt index 6a655b60a8..b3fb29c2b5 100644 --- a/app/src/main/java/com/gh/download/simple/DownloadMessageHandler.kt +++ b/app/src/main/java/com/gh/download/simple/DownloadMessageHandler.kt @@ -2,6 +2,7 @@ package com.gh.download.simple import android.annotation.SuppressLint import android.database.sqlite.SQLiteException +import android.database.sqlite.SQLiteFullException import com.gh.gamecenter.core.utils.ToastUtils import com.lg.download.* import com.lg.download.listener.InnerDownloadListener @@ -174,6 +175,9 @@ object DownloadMessageHandler : InnerDownloadListener { DownloadError.CONTENT_LENGTH_IS_ZERO -> { ToastUtils.toast("下载链接异常,请检查") } + DownloadError.DISK_IS_FULL -> { + ToastUtils.toast("磁盘已满,请清理空间后获得更好的体验") + } else -> { // 想怎么处理就怎么处理 } @@ -264,18 +268,30 @@ object DownloadMessageHandler : InnerDownloadListener { } fun insertDownloadToDatabase(downloadEntity: SimpleDownloadEntity) { - mDownloadDao.insertDownloadEntity(downloadEntity) - updateDownloadList() + try { + mDownloadDao.insertDownloadEntity(downloadEntity) + updateDownloadList() + } catch (e: SQLiteException) { + if (e is SQLiteFullException) { + ToastUtils.showToast("磁盘已满,请清理空间获得更好的体验") + } + e.printStackTrace() + } } fun updateDownloadToDatabase( downloadEntity: SimpleDownloadEntity, updateDownloadList: Boolean = false ) { - mDownloadDao.updateDownloadEntity(downloadEntity) + try { + mDownloadDao.updateDownloadEntity(downloadEntity) - if (updateDownloadList) { - updateDownloadList() + if (updateDownloadList) { + updateDownloadList() + } + } catch (e: SQLiteFullException) { + // 底层的下载服务遇到 SQLiteFullException 时会自动暂停下载任务,上层这里就不用纠结处理方式了 + e.printStackTrace() } } diff --git a/app/src/main/java/com/gh/gamecenter/SplashScreenActivity.kt b/app/src/main/java/com/gh/gamecenter/SplashScreenActivity.kt index 2efd59cad4..81c72a3567 100644 --- a/app/src/main/java/com/gh/gamecenter/SplashScreenActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/SplashScreenActivity.kt @@ -282,11 +282,11 @@ class SplashScreenActivity : BaseActivity(), ISplashScreen { SensorsBridge.init(HaloApp.getInstance(), HaloApp.getInstance().channel) SensorsBridge.setOAID(HaloApp.getInstance().oaid) - val pushProvider = TheRouter.get(IPushProvider::class.java) - val registrationId = pushProvider?.getRegistrationId(this) - if (!registrationId.isNullOrEmpty()) { - SensorsBridge.profileAppend(KEY_REGISTRATION_ID, registrationId) - } +// val pushProvider = ARouter.getInstance().build(RouteConsts.provider.push).navigation() as? IPushProvider +// val registrationId = pushProvider?.getRegistrationId(this) +// if (!registrationId.isNullOrEmpty()) { +// SensorsBridge.profileSet(KEY_REGISTRATION_ID, registrationId) +// } } private fun prefetchData() { diff --git a/app/src/main/java/com/gh/gamecenter/adapter/viewholder/DetailViewHolder.kt b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/DetailViewHolder.kt index 4b359494f2..290ff474bc 100644 --- a/app/src/main/java/com/gh/gamecenter/adapter/viewholder/DetailViewHolder.kt +++ b/app/src/main/java/com/gh/gamecenter/adapter/viewholder/DetailViewHolder.kt @@ -455,17 +455,9 @@ class DetailViewHolder( } ButtonStyle.RESERVED -> { - if ("download" == mGameEntity.reserveStatus) { - ReservationHelper.showDeleteReservationDialog(mViewHolder.context) { - ReservationHelper.deleteReservation(mGameEntity) { - DetailDownloadUtils.updateViewHolder(mViewHolder) - } - } - } else { - ReservationHelper.showCancelReservationDialog(mViewHolder.context, mGameEntity) { - ReservationHelper.cancelReservation(mGameEntity) { - DetailDownloadUtils.updateViewHolder(mViewHolder) - } + ReservationHelper.showCancelReservationDialog(mViewHolder.context, mGameEntity) { + ReservationHelper.cancelReservation(mGameEntity) { + DetailDownloadUtils.updateViewHolder(mViewHolder) } } } diff --git a/app/src/main/java/com/gh/gamecenter/authorization/AuthorizationActivity.kt b/app/src/main/java/com/gh/gamecenter/authorization/AuthorizationActivity.kt index fb85885b31..31b4203c1b 100644 --- a/app/src/main/java/com/gh/gamecenter/authorization/AuthorizationActivity.kt +++ b/app/src/main/java/com/gh/gamecenter/authorization/AuthorizationActivity.kt @@ -1,11 +1,13 @@ package com.gh.gamecenter.authorization +import android.app.Dialog import android.content.Intent import android.os.Build import android.os.Bundle import com.gh.common.util.CheckLoginUtils import com.gh.common.util.DialogUtils import com.gh.common.util.NewFlatLogUtils +import com.gh.common.util.PackageUtils import com.gh.gamecenter.R import com.gh.gamecenter.common.base.activity.ToolBarActivity import com.gh.gamecenter.common.constant.EntranceConsts @@ -16,6 +18,7 @@ import com.gh.gamecenter.common.utils.viewModelProvider import com.gh.gamecenter.core.utils.DisplayUtils import com.gh.gamecenter.databinding.ActivityAuthorizationBinding import com.gh.gamecenter.login.user.UserManager +import com.gh.gamecenter.login.user.UserRepository import com.gh.gamecenter.login.view.LoginActivity import com.gh.vspace.VHelper import com.lightgame.utils.Utils @@ -68,6 +71,8 @@ class AuthorizationActivity : ToolBarActivity() { //授权token private var mToken = "" + private var loadingDialog: Dialog? = null + override fun getLayoutId(): Int { return R.layout.activity_authorization } @@ -80,11 +85,16 @@ class AuthorizationActivity : ToolBarActivity() { mBinding = ActivityAuthorizationBinding.bind(mContentView) checkParam() initView() - mBinding.authorizeBtn.postDelayed({ + mBaseHandler.post { + if (loadingDialog == null) { + loadingDialog = DialogUtils.showWaitDialog(this, "请稍后...") + } + } + UserRepository.getInstance().loginUserInfo.observe(this) { checkLogin { initUserInfo() } - }, 500) + } NewFlatLogUtils.logLoginFromGHZSShow( gameId = gameId, gameName = gameName @@ -97,14 +107,21 @@ class AuthorizationActivity : ToolBarActivity() { } private fun initData() { - if (mToken.isNotEmpty() || isFinishing) return - val loadingDialog = DialogUtils.showWaitDialog(this, "请稍后...") + if (mToken.isNotEmpty() || isFinishing) { + loadingDialog?.dismiss() + return + } + if (loadingDialog == null) { + loadingDialog = DialogUtils.showWaitDialog(this, "请稍后...") + } else if (loadingDialog?.isShowing == false) { + loadingDialog?.show() + } mViewModel.getAccessToken(listOf(mContent), { mToken = it - loadingDialog.dismiss() + loadingDialog?.dismiss() }, { toast("获取token失败") - loadingDialog.dismiss() + loadingDialog?.dismiss() }) } @@ -152,8 +169,8 @@ class AuthorizationActivity : ToolBarActivity() { private fun initView() { //通过包名获取app图标和名称 val pkgName = mRemotePkgName ?: return - val icon = packageManager.getApplicationIcon(pkgName) - val name = packageManager.getApplicationLabel(packageManager.getApplicationInfo(pkgName, 0)) + val icon = PackageUtils.getIconByPackageName(this, pkgName) + val name = PackageUtils.getNameByPackageName(this, pkgName) mBinding.authorizeAppIcon.setImageDrawable(icon) mBinding.authorizeAppName.text = name mBinding.authorizeBtn.setOnClickListener { diff --git a/app/src/main/java/com/gh/gamecenter/gamecollection/square/GameCollectionSquareFragment.kt b/app/src/main/java/com/gh/gamecenter/gamecollection/square/GameCollectionSquareFragment.kt index c3fcb1e224..3a1e3f6308 100644 --- a/app/src/main/java/com/gh/gamecenter/gamecollection/square/GameCollectionSquareFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/gamecollection/square/GameCollectionSquareFragment.kt @@ -209,7 +209,7 @@ class GameCollectionSquareFragment : LazyListFragment(GameCollectionTagSelectFragment.SELECTED_TAG) val tagCategory = data.getStringExtra(GameCollectionTagSelectFragment.SELECTED_TAG_CATEGORY) diff --git a/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt b/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt index 2a3cf72ac4..bc38a53d9e 100644 --- a/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/gamedetail/GameDetailFragment.kt @@ -866,10 +866,11 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable { showConcernIconAtBottomBarIfAvailable() - val downloadEntitySnapshot = DownloadManager.getInstance().getDownloadEntitySnapshot(mGameEntity) + val downloadEntitySnapshot = DownloadManager.getInstance().getDownloadEntitySnapshot(mGameEntity) if (isSpecialDownloadDialogAvailable(downloadEntitySnapshot) - && downloadEntitySnapshot != null) { + && downloadEntitySnapshot != null + ) { updateSpecialDownloadDialogIcon(true) } @@ -1855,19 +1856,10 @@ class GameDetailFragment : BaseLazyFragment(), IScrollable { ) } else { - if ("download" == mGameEntity?.reserveStatus) { - ReservationHelper.showDeleteReservationDialog(requireContext()) { - ReservationHelper.deleteReservation(mGameEntity!!) { - DetailDownloadUtils.updateViewHolder(detailViewHolder) - showReserveBtn(isShowReserveBtn()) - } - } - } else { - ReservationHelper.showCancelReservationDialog(requireContext(), mGameEntity) { - ReservationHelper.cancelReservation(mGameEntity!!) { - DetailDownloadUtils.updateViewHolder(detailViewHolder) - showReserveBtn(isShowReserveBtn()) - } + ReservationHelper.showCancelReservationDialog(requireContext(), mGameEntity) { + ReservationHelper.cancelReservation(mGameEntity!!) { + DetailDownloadUtils.updateViewHolder(detailViewHolder) + showReserveBtn(isShowReserveBtn()) } } } diff --git a/app/src/main/java/com/gh/gamecenter/home/custom/CustomPageFragment.kt b/app/src/main/java/com/gh/gamecenter/home/custom/CustomPageFragment.kt index f813dbc67b..adaa1dea0e 100644 --- a/app/src/main/java/com/gh/gamecenter/home/custom/CustomPageFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/home/custom/CustomPageFragment.kt @@ -3,7 +3,11 @@ package com.gh.gamecenter.home.custom import android.graphics.Color import android.os.Build import android.os.Bundle +import android.view.LayoutInflater import android.view.View +import android.view.ViewGroup +import android.widget.RelativeLayout +import androidx.core.view.updateLayoutParams import androidx.fragment.app.viewModels import androidx.lifecycle.Observer import androidx.recyclerview.widget.RecyclerView @@ -54,6 +58,7 @@ import com.gh.gamecenter.feature.entity.PageLocation import com.gh.gamecenter.feature.exposure.ExposureEvent import com.gh.gamecenter.feature.exposure.ExposureType import com.gh.gamecenter.feature.minigame.MiniGameItemHelper +import com.gh.gamecenter.feature.utils.SentryHelper import com.gh.gamecenter.game.commoncollection.detail.CustomCommonCollectionDetailActivity import com.gh.gamecenter.gamedetail.rating.RatingReplyActivity import com.gh.gamecenter.home.PageConfigure @@ -69,6 +74,9 @@ import com.gh.gamecenter.wrapper.SearchToolbarTabWrapperViewModel import com.halo.assistant.HaloApp import com.lightgame.download.DataWatcher import com.lightgame.download.DownloadEntity +import com.scwang.smartrefresh.layout.api.RefreshLayout +import com.scwang.smartrefresh.layout.constant.RefreshState +import com.shuyu.gsyvideoplayer.video.base.GSYVideoView import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode @@ -179,6 +187,22 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable { viewModel.init(pageConfigure, searchToolbarTabWrapperViewModel, pageLocation) } + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + binding = try { + FragmentCustomBinding.inflate(layoutInflater) + } catch (e: Exception) { + SentryHelper.onEvent( + "VIEW_BINDING_BIND_ERROR", + "digest", e.localizedMessage, + "gid", HaloApp.getInstance().gid + ) + // 玄学,重试一次,该闪退闪退 + FragmentCustomBinding.inflate(layoutInflater) + } + mCachedView = binding.root + return mCachedView + } + override fun getRealLayoutId() = R.layout.fragment_custom override fun onFragmentFirstVisible() { @@ -275,6 +299,9 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable { if (searchBarBinding == null) { binding.reuseSearchBarStub.setOnInflateListener { _, inflated -> searchBarBinding = LayoutSearchBarBinding.bind(inflated) + binding.gameRefresh.updateLayoutParams { + addRule(RelativeLayout.BELOW, R.id.reuseSearchBar) + } initSearchBar(it) } binding.reuseSearchBarStub.inflate() @@ -488,8 +515,6 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable { override fun initRealView() { super.initRealView() - binding = FragmentCustomBinding.bind(mCachedView) - scrollCalculatorHelper = ScrollCalculatorHelper(binding.gameList, R.id.autoVideoView, 0, false) buildPriorityChain() @@ -743,7 +768,7 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable { } } - override fun setScrollEnabled(isScrollEnabled: Boolean) { + private fun setScrollEnabled(isScrollEnabled: Boolean) { if (::layoutManager.isInitialized) { layoutManager.isScrollVerticallyEnabled = isScrollEnabled } @@ -759,6 +784,32 @@ class CustomPageFragment : LazyFragment(), ISmartRefreshContent, IScrollable { } } + override fun onStateChanged(refreshLayout: RefreshLayout, oldState: RefreshState, newState: RefreshState) { + if (oldState == RefreshState.None && newState == RefreshState.PullDownToRefresh) { + pauseVideo() + } else if ((oldState == RefreshState.TwoLevelFinish || oldState == RefreshState.RefreshFinish) && newState == RefreshState.None) { + val currentPlayer = scrollCalculatorHelper.currentPlayer + if (currentPlayer == null) { + scrollCalculatorHelper.playIfValid() + } else if (currentPlayer.currentState == GSYVideoView.CURRENT_STATE_PAUSE) { + resumeVideo() + } + } + + when (newState) { + RefreshState.TwoLevel -> { + setScrollEnabled(false) + } + RefreshState.None -> { + setScrollEnabled(true) + } + + else -> { + // do nothing + } + } + } + override fun scrollToTop() { if (::binding.isInitialized) { binding.gameList.stopScroll() diff --git a/app/src/main/java/com/gh/gamecenter/home/custom/tracker/SubjectTracker.kt b/app/src/main/java/com/gh/gamecenter/home/custom/tracker/SubjectTracker.kt index d595a83ad5..61d1f9e27d 100644 --- a/app/src/main/java/com/gh/gamecenter/home/custom/tracker/SubjectTracker.kt +++ b/app/src/main/java/com/gh/gamecenter/home/custom/tracker/SubjectTracker.kt @@ -65,7 +65,7 @@ class SubjectTracker(private val pageLocation: PageLocation) { pageLocation.pageName, subject?.id ?: "", subject?.name ?: "", - "最近在玩", + "自定义页面", item.componentStyle, "", ) diff --git a/app/src/main/java/com/gh/gamecenter/home/video/ScrollCalculatorHelper.kt b/app/src/main/java/com/gh/gamecenter/home/video/ScrollCalculatorHelper.kt index 961304fa2f..b5c363d0aa 100644 --- a/app/src/main/java/com/gh/gamecenter/home/video/ScrollCalculatorHelper.kt +++ b/app/src/main/java/com/gh/gamecenter/home/video/ScrollCalculatorHelper.kt @@ -29,7 +29,10 @@ class ScrollCalculatorHelper( fun enableAndPlayIfValid() { isEnabled = true + playIfValid() + } + fun playIfValid() { if (mListRv.isAttachedToWindow && mListRv.scrollState == RecyclerView.SCROLL_STATE_IDLE) { playVideo(mListRv) diff --git a/app/src/main/java/com/gh/gamecenter/install/InstallService.kt b/app/src/main/java/com/gh/gamecenter/install/InstallService.kt deleted file mode 100644 index 9288e3064b..0000000000 --- a/app/src/main/java/com/gh/gamecenter/install/InstallService.kt +++ /dev/null @@ -1,93 +0,0 @@ -package com.gh.gamecenter.install - -import android.app.Notification -import android.app.NotificationChannel -import android.app.NotificationManager -import android.app.Service -import android.content.Intent -import android.os.Build -import android.os.IBinder -import androidx.core.app.NotificationCompat -import com.lightgame.download.ForegroundNotificationManager -import com.lightgame.utils.Utils -import java.util.* - -class InstallService : Service() { - - private var mForegroundTimer: Timer? = null - private var mForegroundNotificationManager: ForegroundNotificationManager? = null - - override fun onCreate() { - super.onCreate() - mForegroundNotificationManager = ForegroundNotificationManager(this, this.application) - Utils.log(InstallService::class.java.simpleName, "onCreate") - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - Utils.log(InstallService::class.java.simpleName, "onStartCommand") - val notificationId = 9999 - if (intent != null && intent.extras != null) { - val serviceAction = intent.getStringExtra(KEY_SERVICE_ACTION) - if (START_FOREGROUND == serviceAction) { - startForegroundIfNeeded(notificationId) - } else if (STOP_FOREGROUND == serviceAction) { - startForegroundIfNeeded(notificationId) - stopForegroundIfNeeded(notificationId) - } - } else { - startForegroundIfNeeded(notificationId) - stopForegroundIfNeeded(notificationId) - } - - // 不需要 intent 为空的重建 - return START_NOT_STICKY - } - - override fun onBind(intent: Intent?): IBinder? { - return null - } - - private fun startForegroundIfNeeded(notificationId: Int) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val channel = - NotificationChannel(SERVICE_CHANNEL_ID, SERVICE_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW) - val manager = applicationContext.getSystemService(NOTIFICATION_SERVICE) as NotificationManager - manager.createNotificationChannel(channel) - val notification: Notification = NotificationCompat.Builder(this, SERVICE_CHANNEL_ID) - .setSmallIcon(com.lightgame.R.drawable.ic_download_notification) - .setContentTitle("光环助手安装服务") - .build() - mForegroundNotificationManager?.notify(notificationId, notification) - - mForegroundTimer?.cancel() - mForegroundTimer = Timer() - - val task: TimerTask = object : TimerTask() { - override fun run() { - stopForegroundIfNeeded(notificationId) - } - } - - mForegroundTimer?.schedule(task, FOREGROUND_COUNT_DOWN_TIME) - } - } - - private fun stopForegroundIfNeeded(notificationId: Int) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - mForegroundNotificationManager?.cancel(notificationId) - - mForegroundTimer?.cancel() - mForegroundTimer = null - } - } - - - companion object { - private const val SERVICE_CHANNEL_ID = "安装服务" - private const val FOREGROUND_COUNT_DOWN_TIME = 20 * 1000L - - const val START_FOREGROUND = "start_foreground" - const val STOP_FOREGROUND = "stop_foreground" - const val KEY_SERVICE_ACTION = "service_action" - } -} \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/minigame/MiniGameSearchDefaultRankAdapter.kt b/app/src/main/java/com/gh/gamecenter/minigame/MiniGameSearchDefaultRankAdapter.kt index 5a72006a50..148b83ee21 100644 --- a/app/src/main/java/com/gh/gamecenter/minigame/MiniGameSearchDefaultRankAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/minigame/MiniGameSearchDefaultRankAdapter.kt @@ -59,7 +59,7 @@ class MiniGameSearchDefaultRankAdapter( _id = rank.id, mName = rank.name, miniGameAppId = rank.link.link ?: "", - miniGameType = Constants.WECHAT_MINI_GAME, + miniGameCategory = Constants.WECHAT_MINI_GAME, usage = rank.usage ?: 0 ) holder.binding.playCount.visibility = View.VISIBLE diff --git a/app/src/main/java/com/gh/gamecenter/minigame/MiniGameSearchResultRepository.kt b/app/src/main/java/com/gh/gamecenter/minigame/MiniGameSearchResultRepository.kt index 9bb1a924d6..2b066ac680 100644 --- a/app/src/main/java/com/gh/gamecenter/minigame/MiniGameSearchResultRepository.kt +++ b/app/src/main/java/com/gh/gamecenter/minigame/MiniGameSearchResultRepository.kt @@ -21,6 +21,10 @@ class MiniGameSearchResultRepository( return api.getSearchMiniGameList(key, page, 20) } + override fun getSearchMiniGameCPM(key: String?): Observable> { + return Observable.just(emptyList()) + } + override fun getSearchSubject(key: String?, page: Int): Observable> { return Observable.just(emptyList()) } diff --git a/app/src/main/java/com/gh/gamecenter/minigame/wechat/WGameSubjectCPMRemoteDataSource.kt b/app/src/main/java/com/gh/gamecenter/minigame/wechat/WGameSubjectCPMRemoteDataSource.kt index 00ad669131..de64be3da4 100644 --- a/app/src/main/java/com/gh/gamecenter/minigame/wechat/WGameSubjectCPMRemoteDataSource.kt +++ b/app/src/main/java/com/gh/gamecenter/minigame/wechat/WGameSubjectCPMRemoteDataSource.kt @@ -40,7 +40,8 @@ class WGameSubjectCPMRemoteDataSource( mBrief = info.briefIntro, miniGameUid = info.appID, miniGameAppId = info.userName, - miniGameType = Constants.WECHAT_MINI_GAME_CPM, + miniGameCategory = Constants.WECHAT_MINI_GAME, + profit = Constants.WECHAT_MINI_GAME_PROFIT_CPM, miniGameAppStatus = 2, miniGameAppPath = info.wechatAppPath, miniGameExtData = info.extData, @@ -83,7 +84,8 @@ class WGameSubjectCPMRemoteDataSource( mBrief = info.briefIntro, miniGameUid = info.appID, miniGameAppId = info.userName, - miniGameType = Constants.WECHAT_MINI_GAME_CPM, + miniGameCategory = Constants.WECHAT_MINI_GAME, + profit = Constants.WECHAT_MINI_GAME_PROFIT_CPM, miniGameAppStatus = 2, miniGameAppPath = info.wechatAppPath, miniGameExtData = info.extData, diff --git a/app/src/main/java/com/gh/gamecenter/provider/GhContentProvider.kt b/app/src/main/java/com/gh/gamecenter/provider/GhContentProvider.kt index 0a219f4eb7..3efd79d09f 100644 --- a/app/src/main/java/com/gh/gamecenter/provider/GhContentProvider.kt +++ b/app/src/main/java/com/gh/gamecenter/provider/GhContentProvider.kt @@ -3,6 +3,7 @@ package com.gh.gamecenter.provider import android.content.* import android.database.Cursor import android.database.sqlite.SQLiteDatabase +import android.database.sqlite.SQLiteException import android.database.sqlite.SQLiteFullException import android.database.sqlite.SQLiteOpenHelper import android.net.Uri @@ -12,6 +13,7 @@ import com.gh.gamecenter.BuildConfig import com.gh.gamecenter.common.constant.Constants import com.gh.gamecenter.core.utils.GsonUtils import com.gh.gamecenter.core.utils.SPUtils +import com.gh.gamecenter.core.utils.ToastUtils import com.gh.gamecenter.login.entity.UserInfoEntity import com.gh.gamecenter.login.user.UserRepository import com.halo.assistant.HaloApp @@ -77,7 +79,12 @@ class GhContentProvider : ContentProvider() { } override fun onCreate(): Boolean { - initProviderSqliteHelper(context); + try { + val context = context ?: return false + initProviderSqliteHelper(context) + } catch (e: SQLiteException) { + ToastUtils.toast("数据库内存已满,无法同步") + } return true } diff --git a/app/src/main/java/com/gh/gamecenter/receiver/PackageChangeBroadcastReceiver.java b/app/src/main/java/com/gh/gamecenter/receiver/PackageChangeBroadcastReceiver.java index b32f4eb010..19f2a2000a 100644 --- a/app/src/main/java/com/gh/gamecenter/receiver/PackageChangeBroadcastReceiver.java +++ b/app/src/main/java/com/gh/gamecenter/receiver/PackageChangeBroadcastReceiver.java @@ -19,7 +19,6 @@ import com.gh.gamecenter.core.utils.SPUtils; import com.gh.gamecenter.entity.NewApiSettingsEntity; import com.gh.gamecenter.eventbus.EBPackage; import com.gh.gamecenter.feature.entity.GameInstall; -import com.gh.gamecenter.install.InstallService; import com.gh.gamecenter.manager.PackagesManager; import com.halo.assistant.HaloApp; import com.lightgame.download.DownloadEntity; @@ -27,8 +26,6 @@ import com.lightgame.utils.Utils; import org.greenrobot.eventbus.EventBus; -import java.util.Locale; - /** * 监听安装包变更 */ @@ -49,14 +46,6 @@ public class PackageChangeBroadcastReceiver extends BroadcastReceiver { PackageHelper.INSTANCE.dumpInstalledListCache(); ExtensionsKt.doOnMainProcessOnly(() -> { Utils.log(TAG, "onReceive->" + intent.getAction() + "==" + intent.getDataString()); - - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU - && Build.MANUFACTURER.toLowerCase(Locale.CHINA).contains("xiaomi")) { - Intent foregroundServiceIntent = new Intent(context, InstallService.class); - foregroundServiceIntent.putExtra(InstallService.KEY_SERVICE_ACTION, InstallService.STOP_FOREGROUND); - context.startForegroundService(foregroundServiceIntent); - } - // 接收安装广播 if (intent.getAction().equals(mActions.getAdd())) { String packageName = intent.getDataString(); diff --git a/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java b/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java index 27156754cc..be57a4a531 100644 --- a/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java +++ b/app/src/main/java/com/gh/gamecenter/retrofit/service/ApiService.java @@ -318,6 +318,12 @@ public interface ApiService { @GET Observable> getSearchGame(@Url String url); + /** + * 搜索CPM微信小游戏 + */ + @GET("mini_game/search/configs") + Observable> getSearchWechatMiniCPMGame(@Query("keyword") String key); + /** * 游戏搜索的专题数据 */ diff --git a/app/src/main/java/com/gh/gamecenter/search/ISearchGameResultRepository.kt b/app/src/main/java/com/gh/gamecenter/search/ISearchGameResultRepository.kt index 8fe78d65b0..36e3db7110 100644 --- a/app/src/main/java/com/gh/gamecenter/search/ISearchGameResultRepository.kt +++ b/app/src/main/java/com/gh/gamecenter/search/ISearchGameResultRepository.kt @@ -8,6 +8,8 @@ import io.reactivex.Single interface ISearchGameResultRepository { fun getSearchGame(key: String?, page: Int): Observable> + fun getSearchMiniGameCPM(key: String?): Observable> + fun getSearchSubject(key: String?, page: Int): Observable> fun getWGameCPMGameList(): Single> diff --git a/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexItemViewHolder.kt b/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexItemViewHolder.kt index 78f0b890bc..3f957ca54c 100644 --- a/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexItemViewHolder.kt +++ b/app/src/main/java/com/gh/gamecenter/search/SearchGameIndexItemViewHolder.kt @@ -86,7 +86,7 @@ class SearchSubjectItemViewHolder(var binding: SearchSubjectItemBinding) : Recyc binding.run { subjectRv.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false) - subjectRv.adapter = SearchSubjectAdapter(context, entity.getFilterGame(), "($type-专题)", key) { + subjectRv.adapter = SearchSubjectAdapter(context, entity.getFilterGame(), entity.columnId, entity.name, "($type-专题)", key) { dao?.add(key) if (itemData.adConfig != null) { NewFlatLogUtils.logClickGameAd( diff --git a/app/src/main/java/com/gh/gamecenter/search/SearchGameResultFragment.kt b/app/src/main/java/com/gh/gamecenter/search/SearchGameResultFragment.kt index e346e01630..5055f13d8f 100644 --- a/app/src/main/java/com/gh/gamecenter/search/SearchGameResultFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/search/SearchGameResultFragment.kt @@ -373,12 +373,15 @@ open class SearchGameResultFragment : ListFragment? = null + override fun getSearchGame( key: String?, page: Int @@ -31,6 +38,21 @@ class SearchGameResultRepository( ) } + override fun getSearchMiniGameCPM(key: String?): Observable> { + val currentMiniGameCPMSearchList = currentMiniGameCPMSearchList + if (key == currentSearchKey && currentMiniGameCPMSearchList != null) { + return Observable.just(currentMiniGameCPMSearchList) + } + return mNewApi.getSearchWechatMiniCPMGame(key) + .timeout(5, TimeUnit.SECONDS) + .onErrorReturnItem(emptyList()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext { + this.currentSearchKey = key + this.currentMiniGameCPMSearchList = it + } + } + override fun getSearchSubject(key: String?, page: Int): Observable> { return mApi.getSearchSubject(key, page) } diff --git a/app/src/main/java/com/gh/gamecenter/search/SearchGameResultViewModel.kt b/app/src/main/java/com/gh/gamecenter/search/SearchGameResultViewModel.kt index e554a9e5b2..acfbbdbf25 100644 --- a/app/src/main/java/com/gh/gamecenter/search/SearchGameResultViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/search/SearchGameResultViewModel.kt @@ -67,15 +67,27 @@ class SearchGameResultViewModel( @SuppressLint("CheckResult") private fun decorateListAndPost(list: MutableList) { - val itemDataList = ArrayList( - list.mapIndexed { index, game -> - SearchItemData(game = game, gamePosition = index, isFirst = index == 0) - } - ) + val itemDataList = ArrayList() + val combineGameList = list.toMutableList() refreshWrongInstallStatus() - repository.getSearchSubject(mSearchKey, mPage) + repository.getSearchMiniGameCPM(mSearchKey) + .zipWith(repository.getSearchSubject(mSearchKey, mPage)) { cpmGameList, subjectList -> // CPM游戏搜索结果列表合并 + for (cpmGame in cpmGameList) { + if (cpmGame.location <= 0 || cpmGame.location > list.size) { + combineGameList.add(cpmGame) + } else { + combineGameList.add(cpmGame.location - 1, cpmGame) + } + } + itemDataList.addAll( + combineGameList.mapIndexed { index, game -> + SearchItemData(game = game, gamePosition = index, isFirst = index == 0) + } + ) + subjectList + } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ mutableList -> diff --git a/app/src/main/java/com/gh/gamecenter/search/SearchSubjectAdapter.kt b/app/src/main/java/com/gh/gamecenter/search/SearchSubjectAdapter.kt index 7e54d0ae79..d4235aac95 100644 --- a/app/src/main/java/com/gh/gamecenter/search/SearchSubjectAdapter.kt +++ b/app/src/main/java/com/gh/gamecenter/search/SearchSubjectAdapter.kt @@ -13,6 +13,8 @@ import com.lightgame.adapter.BaseRecyclerAdapter class SearchSubjectAdapter( context: Context, private val mList: List, + private val mColumnId: String, + private val mColumnName: String, private val mEntrance: String, private val mKey: String, private val clickCallback: ((GameEntity) -> Unit) @@ -40,7 +42,10 @@ class SearchSubjectAdapter( MiniGameItemHelper.launchMiniGame(gameEntity) MiniGameItemHelper.trackMiniGameClick( gameEntity = gameEntity, + gameColumnId = mColumnId, + gameColumnName = mColumnName, location = "小游戏搜索结果列表", + position = position, searchContent = mKey, ) } else { diff --git a/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameListViewModel.kt b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameListViewModel.kt index 4f71178f1a..45da54071e 100644 --- a/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameListViewModel.kt +++ b/app/src/main/java/com/gh/gamecenter/simulatorgame/SimulatorGameListViewModel.kt @@ -1,6 +1,7 @@ package com.gh.gamecenter.simulatorgame import android.app.Application +import android.database.sqlite.SQLiteException import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import com.gh.common.simulator.SimulatorGameManager @@ -46,8 +47,12 @@ class SimulatorGameListViewModel(application: Application, var type: String) : simulatorGameRecordList.add(gameEntity.convertSimulatorGameRecordEntity()) } } - mSimulatorGameDao.addSimulatorGameList(simulatorGameRecordList) - mResultLiveData.postValue(newList) + try { + mSimulatorGameDao.addSimulatorGameList(simulatorGameRecordList) + mResultLiveData.postValue(newList) + } catch (e: SQLiteException) { + e.printStackTrace() + } } } diff --git a/app/src/main/java/com/gh/gamecenter/wrapper/SearchToolbarTabWrapperFragment.kt b/app/src/main/java/com/gh/gamecenter/wrapper/SearchToolbarTabWrapperFragment.kt index 96b1e3e20e..5ae22a1075 100644 --- a/app/src/main/java/com/gh/gamecenter/wrapper/SearchToolbarTabWrapperFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/wrapper/SearchToolbarTabWrapperFragment.kt @@ -562,6 +562,8 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar oldState: RefreshState, newState: RefreshState ) { + getValidSmartRefreshContent()?.onStateChanged(refreshLayout, oldState, newState) + val isAutoScrollToTwoLevel = oldState == RefreshState.None && newState == RefreshState.TwoLevel val isDragToTwoLevel = oldState == RefreshState.ReleaseToRefresh && newState == RefreshState.ReleaseToTwoLevel @@ -659,49 +661,17 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar if (isFinishTwoLevel) { pausePullDownPushVideo() - showTwoLevel = false - if (isDragging) { - autoFinishTwoLevelHandler?.removeMessages(KEY_AUTO_FINISH_TWO_LEVEL) - elapsedHelper.pauseCounting() - pullDownPush?.run { - SensorsBridge.trackEvent( - "DropDownPushClick", - json { - "action" to pullDownPushAction - "button_name" to "关闭推送" - "drop_down_push_id" to id - "game_name" to game?.name - "game_id" to game?.id - "bottom_tab" to bottomTabName - "several_tab_page_name" to multiTabNavName - "several_tab_page_id" to multiTabNavId - "position" to lastSelectedPosition - "tab_content" to currentTabEntity?.name - "custom_page_name" to currentTabEntity?.link?.text - "custom_page_id" to currentTabEntity?.link?.link - } - ) - com.gh.common.util.NewFlatLogUtils.logHomePushClose( - id, - "主动收起", - twoLevelOpenCount, - game?.id ?: "", - game?.name ?: "", - elapsedHelper.elapsedTime - ) - } + finishTwoLevel("主动收起") } + showTwoLevel = false } when (newState) { RefreshState.TwoLevel -> { - getValidSmartRefreshContent()?.setScrollEnabled(false) binding.refreshLayout.isDisableContent = false } RefreshState.None -> { - getValidSmartRefreshContent()?.setScrollEnabled(true) - showTwoLevel = false isDragging = false twoLevelHeader.setFloorDuration(1000) @@ -945,6 +915,7 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar classicsHeader.visibility = View.INVISIBLE pullDownPushSet.add(id) SPUtils.setStringSet(Constants.SP_PULL_DOWN_PUSH_POP_UP_SET, pullDownPushSet) + autoFinishTwoLevelCallback = finishCallback autoFinishTwoLevelHandler = object : Handler(Looper.getMainLooper()) { override fun handleMessage(msg: Message) { super.handleMessage(msg) @@ -966,9 +937,6 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar val autoFinishDelayTime = putAwaySwitch.toInt() * 1000L autoFinishTwoLevelHandler?.sendEmptyMessageDelayed(KEY_AUTO_FINISH_TWO_LEVEL, autoFinishDelayTime) } - else -> { - autoFinishTwoLevelCallback = finishCallback - } } } } @@ -983,7 +951,11 @@ class SearchToolbarTabWrapperFragment : BaseTabWrapperFragment(), ISearchToolbar autoVideoView = LayoutAutoVideoViewBinding.bind(inflated).root setPullDownPushInternal(pullDownPush, pullDownPushHandler) } - binding.autoVideoViewStub.inflate() + try { + binding.autoVideoViewStub.inflate() + } catch (e: Exception) { + SentryHelper.onEvent("VIEW_STUB_INFLATE_ERROR", "digest", e.localizedMessage) + } } else { setPullDownPushInternal(pullDownPush, pullDownPushHandler) } diff --git a/app/src/main/java/com/gh/gamecenter/wrapper/TabWrapperFragment.kt b/app/src/main/java/com/gh/gamecenter/wrapper/TabWrapperFragment.kt index dd382663a8..ee0d2a4cb8 100644 --- a/app/src/main/java/com/gh/gamecenter/wrapper/TabWrapperFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/wrapper/TabWrapperFragment.kt @@ -21,6 +21,8 @@ import com.gh.gamecenter.entity.MultiTabNav import com.gh.gamecenter.entity.PullDownPush import com.gh.gamecenter.feature.utils.SentryHelper import com.google.android.material.tabs.TabLayout +import com.scwang.smartrefresh.layout.api.RefreshLayout +import com.scwang.smartrefresh.layout.constant.RefreshState import kotlin.math.roundToInt /** @@ -148,10 +150,6 @@ class TabWrapperFragment: BaseTabWrapperFragment(), ISmartRefresh, ISmartRefresh } } - override fun setScrollEnabled(isScrollEnabled: Boolean) { - getValidSmartRefreshContent()?.setScrollEnabled(isScrollEnabled) - } - override fun onRefresh() { getValidSmartRefreshContent()?.onRefresh() } @@ -161,6 +159,10 @@ class TabWrapperFragment: BaseTabWrapperFragment(), ISmartRefresh, ISmartRefresh getCurrentTabEntity()?.showPullDownPush = !isSwipeRefreshEnabled } + override fun onStateChanged(refreshLayout: RefreshLayout, oldState: RefreshState, newState: RefreshState) { + getValidSmartRefreshContent()?.onStateChanged(refreshLayout, oldState, newState) + } + override fun setSmartRefreshEnabled(isEnable: Boolean) { (parentFragment as? ISmartRefresh)?.setSmartRefreshEnabled(isEnable) } diff --git a/app/src/main/java/com/gh/gamecenter/wrapper/ToolbarWrapperFragment.kt b/app/src/main/java/com/gh/gamecenter/wrapper/ToolbarWrapperFragment.kt index 169d10a0c0..00b7b82c5b 100644 --- a/app/src/main/java/com/gh/gamecenter/wrapper/ToolbarWrapperFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/wrapper/ToolbarWrapperFragment.kt @@ -434,6 +434,8 @@ class ToolbarWrapperFragment : LazyFragment(), ToolbarController, ISmartRefresh, oldState: RefreshState, newState: RefreshState ) { + (mContentFragment as? ISmartRefreshContent)?.onStateChanged(refreshLayout, oldState, newState) + val isAutoScrollToTwoLevel = oldState == RefreshState.None && newState == RefreshState.TwoLevel val isDragToTwoLevel = oldState == RefreshState.ReleaseToRefresh && newState == RefreshState.ReleaseToTwoLevel @@ -550,12 +552,9 @@ class ToolbarWrapperFragment : LazyFragment(), ToolbarController, ISmartRefresh, when (newState) { RefreshState.TwoLevel -> { - (mContentFragment as? ISmartRefreshContent)?.setScrollEnabled(false) mBinding.refreshLayout.isDisableContent = false } RefreshState.None -> { - (mContentFragment as? ISmartRefreshContent)?.setScrollEnabled(true) - mShowTwoLevel = false mIsDragging = false twoLevelHeader.setFloorDuration(1000) diff --git a/app/src/main/java/com/gh/vspace/VGameInstalledLaunchDialog.kt b/app/src/main/java/com/gh/vspace/VGameInstalledLaunchDialog.kt index d10c23d061..f1320014c4 100644 --- a/app/src/main/java/com/gh/vspace/VGameInstalledLaunchDialog.kt +++ b/app/src/main/java/com/gh/vspace/VGameInstalledLaunchDialog.kt @@ -9,6 +9,8 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.FragmentTransaction +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel import androidx.recyclerview.widget.* import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback import androidx.viewpager2.widget.ViewPager2.PageTransformer @@ -77,9 +79,7 @@ class VGameInstalledLaunchDialog : DialogFragment() { val newInstalledList = (installAdapter.currentList + installGameEntity).sortedWith { o1, o2 -> (o1.installTime - o2.installTime).toInt() } - installAdapter.submitList(newInstalledList) { - updateGameDesc(newInstalledList.size) - } + installAdapter.submitList(newInstalledList) } @Deprecated("Deprecated in Java") @@ -123,7 +123,7 @@ class VGameInstalledLaunchDialog : DialogFragment() { val horizontalPadding = ((DIALOG_WIDTH - VIEW_PAGER_WIDTH) / 2).dip2px() setPadding(horizontalPadding, 0, horizontalPadding, 0) - adapter = installAdapter + adapter = installAdapter.apply { setOnCommitCallback { updateGameDesc(it) } } layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false) @@ -140,7 +140,8 @@ class VGameInstalledLaunchDialog : DialogFragment() { it.registerOnPageChangeCallback(object : OnPageChangeCallback() { override fun onPageSelected(position: Int) { val currentList = installAdapter.currentList - gameName.text = currentList[position].gameName + val item = currentList.safelyGetInRelease(position) ?: return + gameName.text = item.gameName } }) @@ -180,6 +181,11 @@ class VGameInstalledLaunchDialog : DialogFragment() { } } + override fun onDestroyView() { + super.onDestroyView() + installAdapter.setOnCommitCallback(null) + } + private fun updateGameDesc(size: Int) { binding?.gameDesc?.text = if (size == 1) { getString(R.string.dialog_vgame_installed_launch_desc_1) @@ -188,9 +194,7 @@ class VGameInstalledLaunchDialog : DialogFragment() { } } - class VInstalledGameListAdapter( - - ) : ListAdapter(COMPARATOR) { + class VInstalledGameListAdapter: ListAdapter(COMPARATOR) { companion object { private val COMPARATOR = object : DiffUtil.ItemCallback() { @@ -212,12 +216,18 @@ class VGameInstalledLaunchDialog : DialogFragment() { } } + private var onCommitCallback: ((Int) -> Unit)? = null + private var onItemClickListener: ((View, Int) -> Unit)? = null fun setOnItemClickListener(onItemClick: (View, Int) -> Unit) { this.onItemClickListener = onItemClick } + fun setOnCommitCallback(onCommitCallback: ((Int) -> Unit)?) { + this.onCommitCallback = onCommitCallback + } + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VInstalledGameItemViewHolder = VInstalledGameItemViewHolder( ItemVgameInstalledLaunchBinding.inflate( @@ -235,6 +245,12 @@ class VGameInstalledLaunchDialog : DialogFragment() { onItemClickListener?.invoke(it, position) } } + + override fun submitList(list: List?) { + super.submitList(list) { + onCommitCallback?.invoke(itemCount) + } + } } class VInstalledGameItemViewHolder(val binding: ItemVgameInstalledLaunchBinding) : diff --git a/app/src/main/java/com/gh/vspace/VHelper.kt b/app/src/main/java/com/gh/vspace/VHelper.kt index 897d459370..348abab274 100644 --- a/app/src/main/java/com/gh/vspace/VHelper.kt +++ b/app/src/main/java/com/gh/vspace/VHelper.kt @@ -6,6 +6,7 @@ import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.database.sqlite.SQLiteDiskIOException +import android.database.sqlite.SQLiteException import android.database.sqlite.SQLiteFullException import android.net.Uri import android.os.Build diff --git a/app/src/main/java/com/halo/assistant/HaloApp.java b/app/src/main/java/com/halo/assistant/HaloApp.java index 50281b9310..0be06d3309 100644 --- a/app/src/main/java/com/halo/assistant/HaloApp.java +++ b/app/src/main/java/com/halo/assistant/HaloApp.java @@ -56,7 +56,6 @@ import com.gh.gamecenter.common.utils.DeviceUtils; import com.gh.gamecenter.common.utils.EnvHelper; import com.gh.gamecenter.common.utils.ExtensionsKt; import com.gh.gamecenter.common.utils.ImageUtils; -import com.gh.gamecenter.common.utils.SensorsBridge; import com.gh.gamecenter.core.AppExecutor; import com.gh.gamecenter.core.iinterface.IApplication; import com.gh.gamecenter.core.provider.IFlavorProvider; @@ -340,7 +339,8 @@ public class HaloApp extends MultiDexApplication { OAIDHelper.INSTANCE.getOAID(HaloApp.this, (s, isSuccess) -> { setOAID(s); MetaUtil.INSTANCE.refreshMeta(); - SensorsBridge.INSTANCE.setOAID(s); + + DataUtils.bindValidOaidToSensor(true); if (getGid() != null) { DataUtils.getDeviceCertification(getGid()); diff --git a/app/src/main/res/layout/layout_search_bar.xml b/app/src/main/res/layout/layout_search_bar.xml index 559c8e61de..bfe423e9ae 100644 --- a/app/src/main/res/layout/layout_search_bar.xml +++ b/app/src/main/res/layout/layout_search_bar.xml @@ -1,5 +1,6 @@ 微信小游戏PCS参数 */ @@ -471,6 +472,10 @@ public class Constants { public static final String SP_BRAND_NEW_FIRST_LAUNCH_TIME = "brand_new_first_launch_time"; // 全新安装用户首次启动时间 + public static final String INVALID_OAID_1 = "00000000-0000-0000-0000-000000000000"; + public static final String INVALID_OAID_2 = "0000000000000000000000000000000000000000000000000000000000000000"; + public static final String INVALID_OAID_3 = "00000000000000000000000000000000"; + public static final String IS_RESERVE_ONLINE_REMINDER = "is_reserve_online_reminder"; public static final String TOOL_MAP_PACKAGE_NAME = "com.gh.toolmap";// 光环工具服务APP包名 diff --git a/module_common/src/main/java/com/gh/gamecenter/common/entity/ExposureEntity.kt b/module_common/src/main/java/com/gh/gamecenter/common/entity/ExposureEntity.kt index 903853c491..0ffb0aa1c1 100644 --- a/module_common/src/main/java/com/gh/gamecenter/common/entity/ExposureEntity.kt +++ b/module_common/src/main/java/com/gh/gamecenter/common/entity/ExposureEntity.kt @@ -37,7 +37,7 @@ data class ExposureEntity( @SerializedName("mini_game_type") val miniGameType: String? = "",// 小游戏类型:QQ小游戏:qq 微信小游戏:wechat @SerializedName("mini_game_recommend_id") - val miniGameRecommendId: String? = "", + var miniGameRecommendId: String? = null, var speed: Long = 0, var certification: Int? = null, // 0表示未实名,1表示未成年,2表示成年 diff --git a/module_common/src/main/java/com/gh/gamecenter/common/utils/Extensions.kt b/module_common/src/main/java/com/gh/gamecenter/common/utils/Extensions.kt index 6592645338..84616c976d 100644 --- a/module_common/src/main/java/com/gh/gamecenter/common/utils/Extensions.kt +++ b/module_common/src/main/java/com/gh/gamecenter/common/utils/Extensions.kt @@ -66,7 +66,6 @@ import io.reactivex.SingleTransformer import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable import io.reactivex.schedulers.Schedulers -import okhttp3.MediaType import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.RequestBody import okhttp3.RequestBody.Companion.toRequestBody @@ -1407,11 +1406,13 @@ fun WebView.enableForceDark(isDarkModeOn: Boolean) { false } if (isFeatureSupported) { - WebSettingsCompat.setForceDark( - settings, - if (isDarkModeOn) WebSettingsCompat.FORCE_DARK_ON else WebSettingsCompat.FORCE_DARK_OFF - ) - DarkModeUtils.isWebViewForceDarkEnabled = isDarkModeOn + tryWithDefaultCatch { + WebSettingsCompat.setForceDark( + settings, + if (isDarkModeOn) WebSettingsCompat.FORCE_DARK_ON else WebSettingsCompat.FORCE_DARK_OFF + ) + DarkModeUtils.isWebViewForceDarkEnabled = isDarkModeOn + } } } diff --git a/module_common/src/main/java/com/gh/gamecenter/common/utils/SensorsBridge.kt b/module_common/src/main/java/com/gh/gamecenter/common/utils/SensorsBridge.kt index 23b3fc86c5..3fb5a37ed0 100644 --- a/module_common/src/main/java/com/gh/gamecenter/common/utils/SensorsBridge.kt +++ b/module_common/src/main/java/com/gh/gamecenter/common/utils/SensorsBridge.kt @@ -332,7 +332,7 @@ object SensorsBridge { } fun setOAID(oaid: String) { - if (mIsSensorsEnabled) mSensor?.setOAID(oaid) + if (mIsSensorsEnabled || oaid.isNotEmpty()) mSensor?.setOAID(oaid) } @JvmStatic diff --git a/module_core_feature/src/main/java/com/gh/gamecenter/feature/entity/GameEntity.kt b/module_core_feature/src/main/java/com/gh/gamecenter/feature/entity/GameEntity.kt index f901fb86b0..9dbbf0fc5c 100644 --- a/module_core_feature/src/main/java/com/gh/gamecenter/feature/entity/GameEntity.kt +++ b/module_core_feature/src/main/java/com/gh/gamecenter/feature/entity/GameEntity.kt @@ -284,17 +284,20 @@ data class GameEntity( @SerializedName("message_private_id") var messageId: String = "", - // 小游戏服务商ID,目前仅用于微信小游戏CPM + // 小游戏用户ID,目前仅用于微信小游戏CPM,对应着小游戏的appid字段 + @SerializedName("wxappid") var miniGameUid: String = "", // 小游戏ID,仅用于小游戏 + // 如果是微信小游戏,则对应着小游戏的user_name字段 + // 如果是QQ小游戏,则对应着小游戏的game_id字段 @SerializedName("appid") var miniGameAppId: String = "", // 小游戏状态(1:下架 2:秒玩),仅用于小游戏 @SerializedName("app_status") var miniGameAppStatus: Int = 0, - // 小游戏类型(qq/wechat/wechat_cpm),仅用于小游戏 + // 小游戏类别(qq/wechat),仅用于小游戏 @SerializedName("game_type") - var miniGameType: String = "", + var miniGameCategory: String = "", // 小游戏链接URL,仅用于小游戏 @SerializedName("appidLink") var miniGameAppLink: String = "", @@ -308,10 +311,13 @@ data class GameEntity( var usage: Int = 0, // 游戏封面图,仅用于微信小游戏 var banner: String = "", + // 收益来源(CPM),仅用于微信小游戏 + var profit: String = "", // 宣传图,仅用于微信小游戏 @SerializedName("publicity_img") var publicityImg: List? = null, - + // 小游戏在搜索结果的位置,仅用于微信小游戏CPM搜索结果列表 + var location: Int = -1, @SerializedName("first_setting") var firstSetting: FirstSetting? = null, @SerializedName("bubble_text") @@ -795,6 +801,11 @@ data class GameEntity( return category.equals("gjonline") } + val miniGameType: String get() = when(profit) { + Constants.WECHAT_MINI_GAME_PROFIT_CPM -> Constants.WECHAT_MINI_GAME_CPM + else -> miniGameCategory + } + /** * 当前游戏是否为小游戏 */ diff --git a/module_core_feature/src/main/java/com/gh/gamecenter/feature/exposure/ExposureEvent.kt b/module_core_feature/src/main/java/com/gh/gamecenter/feature/exposure/ExposureEvent.kt index 39f2c4aef4..256cbac77d 100644 --- a/module_core_feature/src/main/java/com/gh/gamecenter/feature/exposure/ExposureEvent.kt +++ b/module_core_feature/src/main/java/com/gh/gamecenter/feature/exposure/ExposureEvent.kt @@ -113,7 +113,7 @@ data class ExposureEvent( miniGameUid = gameEntity?.miniGameUid ?: "", miniGameId = gameEntity?.miniGameAppId ?: "", miniGameType = gameEntity?.miniGameType ?: "", - miniGameRecommendId = gameEntity?.miniGameRecommendId ?: "", + miniGameRecommendId = gameEntity?.miniGameRecommendId, additional = gameEntity?.customPageTrackData?.toKV() ) this.id = UUID.randomUUID().toString() diff --git a/module_core_feature/src/main/java/com/gh/gamecenter/feature/minigame/MiniGameItemHelper.kt b/module_core_feature/src/main/java/com/gh/gamecenter/feature/minigame/MiniGameItemHelper.kt index 2fc0157d99..10f99729ae 100644 --- a/module_core_feature/src/main/java/com/gh/gamecenter/feature/minigame/MiniGameItemHelper.kt +++ b/module_core_feature/src/main/java/com/gh/gamecenter/feature/minigame/MiniGameItemHelper.kt @@ -107,12 +107,7 @@ object MiniGameItemHelper { gameName = gameEntity.name ?: "" ) if (gameEntity.miniGameType == Constants.WECHAT_MINI_GAME_CPM) { - WGameSubjectCPMListReportHelper.reportClick( - miniAppUid = gameEntity.miniGameUid, - gameName = gameEntity.name ?: "", - operateTime = System.currentTimeMillis() / 1000, - recommendId = gameEntity.miniGameRecommendId - ) + WGameSubjectCPMListReportHelper.reportClick(gameEntity) } } } diff --git a/module_core_feature/src/main/java/com/gh/gamecenter/feature/minigame/wechat/WGameSubjectCPMListReportHelper.kt b/module_core_feature/src/main/java/com/gh/gamecenter/feature/minigame/wechat/WGameSubjectCPMListReportHelper.kt index c08c6a8812..6c682a29e2 100644 --- a/module_core_feature/src/main/java/com/gh/gamecenter/feature/minigame/wechat/WGameSubjectCPMListReportHelper.kt +++ b/module_core_feature/src/main/java/com/gh/gamecenter/feature/minigame/wechat/WGameSubjectCPMListReportHelper.kt @@ -7,6 +7,7 @@ import com.gh.gamecenter.common.utils.EnvHelper import com.gh.gamecenter.common.utils.FixedSizeLinkedHashSet import com.gh.gamecenter.common.utils.toRequestBody import com.gh.gamecenter.core.AppExecutor +import com.gh.gamecenter.feature.entity.GameEntity import com.gh.gamecenter.feature.entity.WXMiniGameCPMResponse import com.gh.gamecenter.feature.exposure.ExposureEvent import com.gh.gamecenter.feature.retrofit.RetrofitManager @@ -22,7 +23,38 @@ object WGameSubjectCPMListReportHelper { private val exposureRequestSet by lazy { hashSetOf() } private val exposureCacheSet by lazy { FixedSizeLinkedHashSet(100) } + /** + * recommendId为空,正在调用CPM接口的点击事件集合 + */ + private val pendingRecommendIdClickSet by lazy { hashSetOf() } + fun reportClick( + gameEntity: GameEntity, + operateTime: Long = System.currentTimeMillis() / 1000 + ) { + val recommendId = gameEntity.miniGameRecommendId.ifEmpty { + gameEntity.exposureEvent?.payload?.miniGameRecommendId // 如果游戏实体的recommendId为空,则取它绑定的曝光事件的recommendId + } ?: return + if (recommendId.isNotEmpty()) { + reportClickInner( + miniAppUid = gameEntity.miniGameUid, + gameName = gameEntity.name ?: "", + operateTime = System.currentTimeMillis() / 1000, + recommendId = recommendId + ) + return + } + // 没有曝光事件的点击事件上报是不合理的 + val exposureEvent = gameEntity.exposureEvent ?: return + // 正在调用接口请求获取recommendId,需要等待recommendId回调以后再执行上报 + pendingRecommendIdClickSet.add(WGSubjectPendingClick(operateTime, exposureEvent)) + Utils.log( + "WXGameCPMReport", + "当前微信CPM小游戏正在请求CPM接口获取RecommendId,将延迟到RecommendId获取后上报:${gameEntity.name}, ${gameEntity.miniGameAppId}" + ) + } + + private fun reportClickInner( miniAppUid: String, gameName: String, operateTime: Long, @@ -78,6 +110,69 @@ object WGameSubjectCPMListReportHelper { } fun reportExposure(exposure: ExposureEvent) { + val recommendId = exposure.payload.miniGameRecommendId ?: return + if (recommendId.isEmpty()) {// recommendId为空时,需要请求CPM接口获取recommendId的值 + requestRecommendIdAndReportExposure(exposure) + } else { + reportExposureInner(exposure) + } + } + + /** + * 先请求CPM接口获取RecommendId,再提交曝光事件 + */ + @SuppressLint("CheckResult") + private fun requestRecommendIdAndReportExposure(exposure: ExposureEvent) { + val wxappid = exposure.payload.miniGameUid!! + val meta = MetaUtil.getMeta() + val request = mapOf( + "head" to mapOf( + "busiAppid" to EnvHelper.getWGameCPMBusiAppId(), + "oaid" to (meta.oaid ?: ""), + "manufacturer" to (meta.manufacturer ?: ""), + "mode" to (meta.model ?: ""), + "androidId" to (MetaUtil.getAndroidId()), + "imei" to (MetaUtil.getIMEI()) + ), + "body" to mapOf( + "appIDList" to listOf(wxappid) + ) + ) + Utils.log( + "WXGameCPMReport", + "请求CPM接口获取RecommendId,${exposure.payload.gameName}" + ) + RetrofitManager.getInstance() + .wGameCPMApiService + .getGameInfoList(request.toRequestBody()) + .subscribe({ + if (it.ret == 0 && it.appInfoList.isNotEmpty()) { + exposure.payload.miniGameRecommendId = it.appInfoList[0].recommendID + Utils.log( + "WXGameCPMReport", + "请求CPM接口获取RecommendId成功!${exposure.payload.gameName}, ${exposure.payload.miniGameRecommendId}" + ) + reportExposureInner(exposure)// 上报曝光事件 + pendingRecommendIdClickSet.forEach { click -> + if (click.exposure === exposure) {// 上报延迟的点击事件 + reportClickInner( + miniAppUid = exposure.payload.miniGameUid ?: "", + gameName = exposure.payload.gameName ?: "", + operateTime = click.operateTime, + recommendId = exposure.payload.miniGameRecommendId!! + ) + } + } + } + pendingRecommendIdClickSet.removeAll { + click -> click.exposure === exposure } + }, { + pendingRecommendIdClickSet.removeAll { + click -> click.exposure === exposure } + }) + } + + private fun reportExposureInner(exposure: ExposureEvent) { val recommendId = exposure.payload.miniGameRecommendId ?: return val gameName = exposure.payload.gameName ?: "" if (exposureCacheSet.contains(recommendId)) { @@ -173,4 +268,9 @@ object WGameSubjectCPMListReportHelper { val posCard: Int = 0, val posInCard: Int = 0 ) + + class WGSubjectPendingClick( + val operateTime: Long, + val exposure: ExposureEvent + ) } \ No newline at end of file diff --git a/module_core_feature/src/main/java/com/gh/gamecenter/feature/retrofit/WGameCPMApiService.kt b/module_core_feature/src/main/java/com/gh/gamecenter/feature/retrofit/WGameCPMApiService.kt index c794e67c3a..301285760f 100644 --- a/module_core_feature/src/main/java/com/gh/gamecenter/feature/retrofit/WGameCPMApiService.kt +++ b/module_core_feature/src/main/java/com/gh/gamecenter/feature/retrofit/WGameCPMApiService.kt @@ -21,4 +21,7 @@ interface WGameCPMApiService { @POST("reportexposure") fun reportExposure(@Body body: RequestBody): Single + @POST("getgameinfolist") + fun getGameInfoList(@Body body: RequestBody): Single + } \ No newline at end of file diff --git a/ndownload b/ndownload index 22298a573c..91a183a48b 160000 --- a/ndownload +++ b/ndownload @@ -1 +1 @@ -Subproject commit 22298a573c3a1285c2294fe9967080183cdadc80 +Subproject commit 91a183a48b9fc34fc9dc7b05e1a3046366417d74