Commit 9d0c1a11 authored by wanglei's avatar wanglei

[商业化]优化上报的卡顿问题

parent b869a12c
...@@ -14,7 +14,7 @@ import org.json.JSONObject ...@@ -14,7 +14,7 @@ import org.json.JSONObject
*/ */
object SolarEngineEvent { object SolarEngineEvent {
fun eventSolar(ad: Any?, valueMicros: Long) = Thread { fun eventSolar(ad: Any?, valueMicros: Long) {
val json = JSONObject() val json = JSONObject()
//变现平台 //变现平台
...@@ -72,20 +72,21 @@ object SolarEngineEvent { ...@@ -72,20 +72,21 @@ object SolarEngineEvent {
} }
try { try {
val seAdImpEventModel = SEAdImpEventModel(
adNetworkPlatform,
mediationPlatform,
adType,
adNetworkAppID,
adNetworkADID,
ecpm,
currencyType,
true,
json
)
SolarEngineManager.getInstance().trackAdImpression(seAdImpEventModel)
} catch (e: Exception) { } catch (e: Exception) {
// //
} }
val seAdImpEventModel = SEAdImpEventModel(
adNetworkPlatform, }
mediationPlatform,
adType,
adNetworkAppID,
adNetworkADID,
ecpm,
currencyType,
true,
json
)
SolarEngineManager.getInstance().trackAdImpression(seAdImpEventModel)
}.start()
} }
\ No newline at end of file
...@@ -25,6 +25,11 @@ import com.google.android.gms.ads.rewarded.RewardedAd ...@@ -25,6 +25,11 @@ import com.google.android.gms.ads.rewarded.RewardedAd
import com.google.firebase.analytics.FirebaseAnalytics import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.ktx.Firebase import com.google.firebase.ktx.Firebase
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import org.json.JSONObject import org.json.JSONObject
import java.math.BigDecimal import java.math.BigDecimal
import java.util.Currency import java.util.Currency
...@@ -34,16 +39,17 @@ class AdmobEvent : AdEvent { ...@@ -34,16 +39,17 @@ class AdmobEvent : AdEvent {
override val TAG: String = "AdmobEvent" override val TAG: String = "AdmobEvent"
val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
constructor(adUnit: String, from: String) : super() { constructor(adUnit: String, from: String) : super() {
this.adUnit = adUnit this.adUnit = adUnit
this.from = from this.from = from
} }
fun pullAd( fun pullAd(
responseInfo: ResponseInfo?, responseInfo: ResponseInfo?,
error: LoadAdError? = null, error: LoadAdError? = null,
) { ) = MainScope().launch(Dispatchers.IO) {
var key = "ad_pull" var key = "ad_pull"
val obj = JSONObject() val obj = JSONObject()
obj.put("req_id", reqId) obj.put("req_id", reqId)
...@@ -72,11 +78,10 @@ class AdmobEvent : AdEvent { ...@@ -72,11 +78,10 @@ class AdmobEvent : AdEvent {
key = "ad_pull_error" key = "ad_pull_error"
} }
EventUtils.event(key, ext = obj) EventUtils.event(key, ext = obj)
LogEx.logDebug(TAG, "ad_pull obj=$obj") LogEx.logDebug(TAG, "$key obj=$obj")
} }
fun clickAd(responseInfo: ResponseInfo?) = scope.launch {
fun clickAd(responseInfo: ResponseInfo?) {
val response = responseInfo?.adapterResponses?.getOrNull(0) val response = responseInfo?.adapterResponses?.getOrNull(0)
val obj = JSONObject() val obj = JSONObject()
...@@ -100,7 +105,7 @@ class AdmobEvent : AdEvent { ...@@ -100,7 +105,7 @@ class AdmobEvent : AdEvent {
} }
} }
fun showAd(responseInfo: ResponseInfo?, activity: Activity? = null) { fun showAd(responseInfo: ResponseInfo?, activity: Activity? = null) = scope.launch {
val response = responseInfo?.adapterResponses?.getOrNull(0) val response = responseInfo?.adapterResponses?.getOrNull(0)
val obj = JSONObject() val obj = JSONObject()
obj.put("req_id", reqId) obj.put("req_id", reqId)
...@@ -123,37 +128,59 @@ class AdmobEvent : AdEvent { ...@@ -123,37 +128,59 @@ class AdmobEvent : AdEvent {
LogEx.logDebug(TAG, "ad_show $obj") LogEx.logDebug(TAG, "ad_show $obj")
} }
class EventOnPaidEventListener(private val ad: Any?) : OnPaidEventListener { inner class EventOnPaidEventListener(private val ad: Any?) : OnPaidEventListener {
override fun onPaidEvent(adValue: AdValue) { override fun onPaidEvent(adValue: AdValue) {
ad ?: return ad ?: return
SolarEngineEvent.eventSolar(ad, adValue.valueMicros) onPaidEvent2(ad, adValue)
}
fun onPaidEvent2(ad: Any?, adValue: AdValue) {
scope.launch {
try {
val flag = eventAdRatio()
if (flag) {
SolarEngineEvent.eventSolar(ad, adValue.valueMicros)
eventFireBase(adValue)
eventEvent(adValue)
}
} catch (e: Exception) {
EventUtils.event("onPaidEvent_Error")
}
}
}
fun eventAdRatio(): Boolean {
val adRatio = AdConfigBean.adsConfigBean.adRatio val adRatio = AdConfigBean.adsConfigBean.adRatio
val random = Random.Default.nextInt(1, 100) val random = Random.Default.nextInt(1, 100)
if (random > adRatio) { if (random > adRatio) {
taichiSharedPreferencesEditor.putFloat("TaichiTroasCache", 0f) taichiSharedPreferencesEditor.putFloat("TaichiTroasCache", 0f)
taichiSharedPreferencesEditor.commit() taichiSharedPreferencesEditor.commit()
EventUtils.event("ad_price_limit") EventUtils.event("ad_price_limit")
return return false
} }
return true
}
/**
* 上报给firebase
*/
fun eventFireBase(adValue: AdValue) {
val valueMicros = adValue.valueMicros val valueMicros = adValue.valueMicros
val currencyCode = adValue.currencyCode val currencyCode = adValue.currencyCode
val precision = adValue.precisionType val currentImpressionRevenue = adValue.valueMicros.toDouble() / 1000000.0
val fbLogger = AppEventsLogger.newLogger(MyApplication.appContext) //sp里面的价格值
fbLogger.logPurchase(BigDecimal.valueOf(valueMicros / 1000000), Currency.getInstance(currencyCode)) val previousTaichiTroasCache = taichiPref.getFloat("TaichiTroasCache", 0f)
val obj = JSONObject() //当前缓存加个值
obj.put("valueMicros", valueMicros) val currentTaichiTroasCache = (previousTaichiTroasCache + currentImpressionRevenue).toFloat()
obj.put("currencyCode", currencyCode)
obj.put("precision", precision)
Firebase.analytics.logEvent("ad_price", Bundle().apply { //价值上报阀值
putDouble("valueMicros", valueMicros / 1000000.0) val taichiAdValue = AdConfigBean.adsConfigBean.taichiAdValue / 100f
})
val params = Bundle() val params = Bundle()
val currentImpressionRevenue = adValue.valueMicros.toDouble() / 1000000.0
params.putDouble(FirebaseAnalytics.Param.VALUE, currentImpressionRevenue) params.putDouble(FirebaseAnalytics.Param.VALUE, currentImpressionRevenue)
params.putString(FirebaseAnalytics.Param.CURRENCY, "USD") params.putString(FirebaseAnalytics.Param.CURRENCY, "USD")
LogEx.logDebug("EventOnPaidEventListener", "precisionType=${adValue.precisionType}") LogEx.logDebug("EventOnPaidEventListener", "precisionType=${adValue.precisionType}")
...@@ -165,31 +192,51 @@ class AdmobEvent : AdEvent { ...@@ -165,31 +192,51 @@ class AdmobEvent : AdEvent {
else -> "Invalid" else -> "Invalid"
} }
params.putString("precisionType", precisionType) params.putString("precisionType", precisionType)
Firebase.analytics.logEvent("Ad_Impression_Revenue", params)
val previousTaichiTroasCache = taichiPref.getFloat("TaichiTroasCache", 0f)
val currentTaichiTroasCache = (previousTaichiTroasCache +
currentImpressionRevenue).toFloat()
val taichiAdValue = AdConfigBean.adsConfigBean.taichiAdValue / 100f val fbLogger = AppEventsLogger.newLogger(MyApplication.appContext)
//上报
fbLogger.logPurchase(BigDecimal.valueOf(currentImpressionRevenue), Currency.getInstance(currencyCode))
//上报ad_price
Firebase.analytics.logEvent("ad_price", Bundle().apply {
putDouble("valueMicros", valueMicros / 1000000.0)
})
//上报Ad_Impression_Revenue
Firebase.analytics.logEvent("Ad_Impression_Revenue", params)
//上报Total_Ads_Revenue_001
if (currentTaichiTroasCache >= taichiAdValue) {//如果超过0.01就触发一次tROAS taichi事件 if (currentTaichiTroasCache >= taichiAdValue) {//如果超过0.01就触发一次tROAS taichi事件
val roasbundle = Bundle() val roasbundle = Bundle()
roasbundle.putDouble( roasbundle.putDouble(FirebaseAnalytics.Param.VALUE, currentTaichiTroasCache.toDouble())
FirebaseAnalytics.Param.VALUE,
currentTaichiTroasCache.toDouble()
)
roasbundle.putString(FirebaseAnalytics.Param.CURRENCY, "USD") roasbundle.putString(FirebaseAnalytics.Param.CURRENCY, "USD")
Firebase.analytics.logEvent("Total_Ads_Revenue_001", roasbundle) Firebase.analytics.logEvent("Total_Ads_Revenue_001", roasbundle)
taichiSharedPreferencesEditor.putFloat("TaichiTroasCache", 0f)//重新清零,开始计算 taichiSharedPreferencesEditor.putFloat("TaichiTroasCache", 0f)//重新清零,开始计算
val logger = AppEventsLogger.newLogger(MyApplication.appContext)
val parameters = Bundle() val parameters = Bundle()
parameters.putString(AppEventsConstants.EVENT_PARAM_CURRENCY, "USD") parameters.putString(AppEventsConstants.EVENT_PARAM_CURRENCY, "USD")
logger.logEvent("ad_value", currentTaichiTroasCache.toDouble(), parameters) fbLogger.logEvent("ad_value", currentTaichiTroasCache.toDouble(), parameters)
} else { } else {
taichiSharedPreferencesEditor.putFloat("TaichiTroasCache", currentTaichiTroasCache) taichiSharedPreferencesEditor.putFloat("TaichiTroasCache", currentTaichiTroasCache)
} }
taichiSharedPreferencesEditor.commit() taichiSharedPreferencesEditor.commit()
}
/**
* 上报给服务器
*/
fun eventEvent(adValue: AdValue) {
val valueMicros = adValue.valueMicros
val currencyCode = adValue.currencyCode
val precision = adValue.precisionType
val obj = JSONObject()
obj.put("valueMicros", valueMicros)
obj.put("currencyCode", currencyCode)
obj.put("precision", precision)
var key = "ad_price" var key = "ad_price"
when (ad) { when (ad) {
...@@ -313,10 +360,11 @@ class AdmobEvent : AdEvent { ...@@ -313,10 +360,11 @@ class AdmobEvent : AdEvent {
} }
} }
EventUtils.event(key, ext = obj) EventUtils.event(key, ext = obj)
} }
} }
fun adShowError(adError: AdError) { fun adShowError(adError: AdError) = scope.launch {
val obj = JSONObject() val obj = JSONObject()
obj.put("req_id", reqId) obj.put("req_id", reqId)
obj.put("reason", adError.message) obj.put("reason", adError.message)
......
...@@ -4,66 +4,33 @@ import android.os.Build ...@@ -4,66 +4,33 @@ import android.os.Build
import com.base.appzxhy.BuildConfig import com.base.appzxhy.BuildConfig
import com.base.appzxhy.SpConstObject.ifAgreePrivacy import com.base.appzxhy.SpConstObject.ifAgreePrivacy
import com.base.appzxhy.GlobalConfig import com.base.appzxhy.GlobalConfig
import com.base.appzxhy.business.helper.ReportUtils.doPost import com.base.appzxhy.bean.config.ConfigBean
import com.base.appzxhy.utils.AppPreferences import com.base.appzxhy.utils.AppPreferences
import com.base.appzxhy.utils.LogEx import com.base.appzxhy.utils.LogEx
import org.json.JSONException import okhttp3.Call
import okhttp3.Callback
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import okhttp3.logging.HttpLoggingInterceptor
import org.json.JSONObject import org.json.JSONObject
import java.io.IOException
import java.util.TimeZone import java.util.TimeZone
object EventUtils { object EventUtils {
private val TAG = "EventUtils"
fun event( private val TAG = "EventUtils"
key: String,
value: String? = null,
ext: JSONObject? = null,
) {
if (!ifAgreePrivacy) { private val client = OkHttpClient.Builder().apply {
return if (BuildConfig.DEBUG) {
addInterceptor(HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
})
} }
}.build()
Thread {
var paramJson: String? = ""
try {
val pkg = GlobalConfig.PACKAGE_NAME
val s = JSONObject()
.put("action", key)
.put("value", value)
.put("ext", ext)
val s2 = JSONObject()
.put("${pkg}_3", AppPreferences.getInstance().getString("Equipment", ""))
.put("${pkg}_4", AppPreferences.getInstance().getString("Manufacturer", ""))
.put("${pkg}_5", Build.VERSION.SDK_INT)
.put("${pkg}_9", AppPreferences.getInstance().getString("uuid", ""))
.put("${pkg}_10", AppPreferences.getInstance().getString("gid", ""))
.put("${pkg}_13", "android")
.put("${pkg}_15", "google")
.put("${pkg}_14", BuildConfig.VERSION_CODE)
.put("${pkg}_8", BuildConfig.VERSION_NAME)
.put("${pkg}_24", BuildConfig.BUILD_TYPE)
.put("${pkg}_34", TimeZone.getDefault().getID())
val data = JSONObject()
.put("data", s)
.put("bp", s2)
.toString()
LogEx.logDebug(TAG, "uuid=${AppPreferences.getInstance().getString("uuid", "")}")
LogEx.logDebug(TAG, "gid=${AppPreferences.getInstance().getString("gid", "")}")
paramJson = AESHelper.encrypt(data)
} catch (e: JSONException) {
paramJson = ""
}
LogEx.logDebug(TAG, "url=$url")
doPost(
url,
HashMap(),
paramJson
)
}.start()
}
private val url by lazy { private val url by lazy {
val pkg = GlobalConfig.PACKAGE_NAME val pkg = GlobalConfig.PACKAGE_NAME
...@@ -76,4 +43,64 @@ object EventUtils { ...@@ -76,4 +43,64 @@ object EventUtils {
url.toString() url.toString()
} }
// 获取配置参数
fun getConfigParams(): JSONObject {
val packageName = GlobalConfig.PACKAGE_NAME
val jsonObject = JSONObject()
jsonObject.put("${packageName}_4", Build.MANUFACTURER) // 手机厂商
jsonObject.put("${packageName}_5", Build.VERSION.SDK_INT) // android系统版本号
jsonObject.put("${packageName}_8", BuildConfig.VERSION_NAME) // APP版本号,如:1.1.2
jsonObject.put("${packageName}_9", AppPreferences.getInstance().getString("uuid", "")) // Android id
jsonObject.put("${packageName}_10", AppPreferences.getInstance().getString("gid", "")) // Google advertiser id
jsonObject.put("${packageName}_13", "android") // platform 默认android
jsonObject.put("${packageName}_14", BuildConfig.VERSION_CODE)// android版本,如:13
jsonObject.put("${packageName}_15", "google") // 渠道标识
jsonObject.put("${packageName}_24", BuildConfig.BUILD_TYPE) // 环境
val timeZone: TimeZone = TimeZone.getDefault()
jsonObject.put("${packageName}_34", timeZone.id) // 手机本地时区,值如下格式:America/New_York
return jsonObject
}
fun event(
key: String,
value: String? = null,
ext: JSONObject? = null,
) {
if (BuildConfig.DEBUG || !ifAgreePrivacy || ConfigBean.configBean.noEventKey.contains(key)) {
return
}
val s = JSONObject()
.put("action", key)
.put("value", value)
.put("ext", ext)
val data = JSONObject()
.put("data", s)
.put("bp", getConfigParams())
.toString()
val body = AESHelper.encrypt(data)
.toRequestBody("application/json;charset=utf-8".toMediaTypeOrNull())
val request = Request.Builder()
.url(url)
.post(body)
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
LogEx.logDebug(TAG, "onFailure")
}
override fun onResponse(call: Call, response: Response) {
if (response.code == 200 && response.isSuccessful) {
LogEx.logDebug(TAG, "onResponse 200")
}
}
})
}
} }
\ No newline at end of file
package com.base.appzxhy.business.helper;
import android.text.TextUtils;
import com.base.appzxhy.utils.LogEx;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
public class ReportUtils {
private static String TAG = "ReportUtils";
public static String doPost(String urlPath, Map<String, String> paramsMap, String json) {
try {
HttpURLConnection conn = (HttpURLConnection) new URL(urlPath).openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setConnectTimeout(5000);
if (!TextUtils.isEmpty(json)) {
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Content-Length", Integer.toString(json.getBytes().length));
conn.getOutputStream().write(json.getBytes());
}
StringBuilder result = new StringBuilder();
for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
result.append("&").append(entry.getKey()).append("=").append(entry.getValue());
}
if (result.length() > 0) {
try {
conn.getOutputStream().write(result.substring(1).getBytes());
} catch (Exception e) {
}
} else {
// conn.getOutputStream().write(result.substring(0).getBytes());
}
if (conn.getResponseCode() == 200) {
String s = new BufferedReader(new InputStreamReader(conn.getInputStream())).readLine();
if (!TextUtils.isEmpty(s)) {
} else {
s = "";
}
LogEx.INSTANCE.logDebug(TAG, "code=200", false);
return s;
} else {
LogEx.INSTANCE.logDebug(TAG, "code!=200", false);
}
} catch (Exception e) {
e.printStackTrace();
}
return "{ \"success\": false,\n \"errorMsg\": \"后台服务器开小差了!\",\n \"result\":{}}";
}
}
package com.base.appzxhy.business.push.notification package com.base.appzxhy.business.push.notification
import android.os.Handler
import android.os.HandlerThread
import com.base.appzxhy.MyApplication import com.base.appzxhy.MyApplication
import com.base.appzxhy.bean.push.NotificationSendBean import com.base.appzxhy.bean.push.NotificationSendBean
import com.base.appzxhy.bean.config.PopupConfigBean.Companion.popupConfigBean import com.base.appzxhy.bean.config.PopupConfigBean.Companion.popupConfigBean
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.async
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
/** /**
* 通知悬停 * 通知悬停
*/ */
object NotificationHoverUtils { object NotificationHoverUtils {
private val TAG = "NotificationHoverUtils" private val TAG = "NotificationHoverUtils"
private var handlerThread: HandlerThread? = null private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
private var handler: Handler? = null private var notificationJobs = mutableListOf<Job>()
/** /**
* 发送悬停通知 * 发送悬停通知
*/ */
fun sendHoverNotification(sendBean: NotificationSendBean) { fun sendHoverNotification(sendBean: NotificationSendBean) {
val hoverStatus = popupConfigBean.popupHoverStatus val hoverStatus = popupConfigBean.popupHoverStatus
val hoverCount = popupConfigBean.popupHoverCount val hoverCount = popupConfigBean.popupHoverCount
val hoverDelay = popupConfigBean.popupHoverDelay.toLong() val hoverDelay = popupConfigBean.popupHoverDelay.toLong()
if (!hoverStatus) return
stopNotificationHandler()
if (handlerThread == null) { if (!hoverStatus) return
handlerThread = HandlerThread("NotificationHandlerThread")
handlerThread?.start()
}
// 创建 Handler // 取消之前的任务
if (handler == null) { stopNotificationHandler()
handlerThread?.let {
val looper = it.getLooper() ?: return
handler = Handler(looper)
}
}
for (i in 1..hoverCount) { for (i in 1..hoverCount) {
val time = i * hoverDelay val time = i * hoverDelay
handler?.postDelayed(Runnable { val job = scope.launch {
// LogEx.logDebug(TAG, "handler ${MyApplication.PAUSED_VALUE}") delay(time)
if (MyApplication.PAUSED_VALUE == 1) { if (MyApplication.PAUSED_VALUE != 1) {
handler?.removeCallbacksAndMessages(null) async(Dispatchers.Main) {
} else { NotificationUiUtil.sendCustomNotification(sendBean)
NotificationUiUtil.sendCustomNotification(sendBean) }.await()
} }
}, time) }
notificationJobs.add(job)
} }
} }
private fun stopNotificationHandler() { private fun stopNotificationHandler() {
// 停止 HandlerThread // 取消所有协程任务
if (handler != null) { notificationJobs.forEach { it.cancel() }
handler?.removeCallbacksAndMessages(null) notificationJobs.clear()
} }
if (handlerThread != null) {
handlerThread?.quit() /**
handlerThread = null * 清理资源
} */
handler = null fun destroy() {
stopNotificationHandler()
scope.cancel()
} }
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment