feat: 适配微信 CPM 小游戏的曝光上报逻辑
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
package com.gh.common.exposure
|
||||
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.feature.exposure.ExposureEvent
|
||||
import com.gh.gamecenter.feature.exposure.IExposureStateChangeListener
|
||||
import com.gh.gamecenter.feature.exposure.RecyclerViewExposureHelper
|
||||
@ -14,17 +15,28 @@ class DefaultExposureStateChangeListener : IExposureStateChangeListener {
|
||||
) {
|
||||
val exposureStatus = if (inExposure) "曝光中" else "结束曝光"
|
||||
|
||||
val isCPMExposureEvent = exposureEvent.payload.miniGameType == Constants.WECHAT_MINI_GAME_CPM
|
||||
|
||||
Utils.log(
|
||||
RecyclerViewExposureHelper.TAG,
|
||||
"onExposureStateChange: 名称 ${exposureEvent.payload.gameName} 位置 $position, $exposureStatus"
|
||||
)
|
||||
|
||||
if (isCPMExposureEvent && inExposure) {
|
||||
Utils.log(
|
||||
RecyclerViewExposureHelper.TAG,
|
||||
"上报 CPM 曝光 ${exposureEvent.payload.gameName} ${exposureEvent.id}"
|
||||
)
|
||||
ExposureManager.logCPM(exposureEvent)
|
||||
}
|
||||
|
||||
if (!inExposure
|
||||
&& System.currentTimeMillis() - exposureEvent.timeInMillisecond > RecyclerViewExposureHelper.VALID_EXPOSURE_THRESHOLD
|
||||
&& System.currentTimeMillis() - exposureEvent.timeInMillisecond > DEFAULT_VALID_EXPOSURE_THRESHOLD
|
||||
) {
|
||||
Utils.log(
|
||||
RecyclerViewExposureHelper.TAG,
|
||||
"上报列表曝光 ${exposureEvent.payload.gameName} ${exposureEvent.id},曝光时长为 ${System.currentTimeMillis() - exposureEvent.timeInMillisecond}ms"
|
||||
"上报曝光 ${exposureEvent.payload.gameName} ${exposureEvent.id},是否为 CPM 小游戏 -> ${isCPMExposureEvent}," +
|
||||
"曝光时长为 ${System.currentTimeMillis() - exposureEvent.timeInMillisecond}ms"
|
||||
)
|
||||
|
||||
// 标记当前 ExposureEvent 已经被使用过
|
||||
@ -33,4 +45,9 @@ class DefaultExposureStateChangeListener : IExposureStateChangeListener {
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
// 默认曝光有效时长
|
||||
const val DEFAULT_VALID_EXPOSURE_THRESHOLD = 1000L
|
||||
}
|
||||
|
||||
}
|
||||
@ -90,6 +90,15 @@ object ExposureManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a wechat mini game cpm collection of exposure event.
|
||||
*/
|
||||
fun logCPM(event: ExposureEvent) {
|
||||
AppExecutor.logExecutor.execute {
|
||||
WGameSubjectCPMListReportHelper.reportExposure(event)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param forcedUpload Ignore all restrictions.
|
||||
*/
|
||||
|
||||
@ -55,7 +55,7 @@ import java.util.concurrent.TimeUnit
|
||||
class RecyclerViewExposureHelper(
|
||||
private val recyclerView: RecyclerView,
|
||||
private val lifecycleOwner: LifecycleOwner?,
|
||||
private val exposureStateChangeListener: IExposureStateChangeListener
|
||||
private val exposureStateChangeListener: IExposureStateChangeListener,
|
||||
) : RecyclerView.OnScrollListener() {
|
||||
// 处于曝光中的Item数据集合
|
||||
private val inExposureDataList = ArrayList<InExposureData<ExposureEvent>>()
|
||||
@ -223,14 +223,11 @@ class RecyclerViewExposureHelper(
|
||||
visiblePositionExposureEvent.data.refreshTime()
|
||||
// 当前可见位置不在曝光中集合,代表是从不可见变为可见,那么此 position 开始曝光
|
||||
inExposureDataList.add(visiblePositionExposureEvent)
|
||||
invokeExposureStateChange(
|
||||
visiblePositionExposureEvent.data,
|
||||
visiblePosition,
|
||||
true
|
||||
)
|
||||
invokeExposureStateChange(visiblePositionExposureEvent.data, visiblePosition, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inExposureDataList.filter { inExposureData ->
|
||||
// 过滤出处于曝光中的 position 在当前扫描的时候不再处于可见位了
|
||||
inExposureData !in currentVisibleExposureEventList
|
||||
@ -300,12 +297,6 @@ class RecyclerViewExposureHelper(
|
||||
|
||||
// 获取 position 绑定的曝光数据
|
||||
private fun getExposureDataListByPosition(position: Int): List<InExposureData<ExposureEvent>>? {
|
||||
// // 获取 PageLevel 信息 (覆写在 ExposureEvent.create 时填充的 PageLevel,避免因为线程不一样导致的数据异常)
|
||||
// val pageLevelString = if ((recyclerView.context) is IPageLevelProvider) {
|
||||
// (recyclerView.context as IPageLevelProvider).getPageLevel().toFormatedString()
|
||||
// } else {
|
||||
// ""
|
||||
// }
|
||||
val provideExposureDataViewList =
|
||||
findAllExposureProviderAndAddOnScrollListener(recyclerView.layoutManager?.findViewByPosition(position))
|
||||
if (provideExposureDataViewList.isNullOrEmpty()) {
|
||||
@ -323,8 +314,6 @@ class RecyclerViewExposureHelper(
|
||||
val exposureEventList = it.provideExposureDataList()
|
||||
if (exposureEventList != null) {
|
||||
for (exposureEvent in exposureEventList) {
|
||||
// // 附加 PageLevel 信息
|
||||
// exposureEvent.payload.pageLevel = pageLevelString
|
||||
// 添加到队列里
|
||||
inExposureDataListResult.add(InExposureData(exposureEvent, position))
|
||||
}
|
||||
@ -333,8 +322,6 @@ class RecyclerViewExposureHelper(
|
||||
// 若实现了 IExposureProvider 接口,则调用 provideExposureData 方法获取曝光数据
|
||||
val exposureEvent = it.provideExposureData()
|
||||
if (exposureEvent != null) {
|
||||
// // 附加 PageLevel 信息
|
||||
// exposureEvent.payload.pageLevel = pageLevelString
|
||||
// 添加到队列里
|
||||
inExposureDataListResult.add(InExposureData(exposureEvent, position))
|
||||
}
|
||||
@ -431,7 +418,6 @@ class RecyclerViewExposureHelper(
|
||||
const val TAG = "RecyclerViewExposureHelper"
|
||||
|
||||
const val VALID_VISIBLE_RECT_PERCENTAGE = 0.7F
|
||||
const val VALID_EXPOSURE_THRESHOLD = 1000L
|
||||
const val SAMPLE_RATE = 100L
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user