diff --git a/StatisticReporter/build.gradle.kts b/StatisticReporter/build.gradle.kts index af4a3ab..209ed47 100644 --- a/StatisticReporter/build.gradle.kts +++ b/StatisticReporter/build.gradle.kts @@ -47,4 +47,5 @@ dependencies { api("com.adjust.sdk:adjust-android-webbridge:5.5.0") api("com.android.installreferrer:installreferrer:2.2") api("com.adjust.sdk:adjust-android-huawei-referrer:5.0.0") + api("com.google.android.gms:play-services-ads-identifier:18.2.0") } \ No newline at end of file diff --git a/StatisticReporter/src/main/java/com/gamedog/statisticreporter/adjust/AdjustManager.kt b/StatisticReporter/src/main/java/com/gamedog/statisticreporter/adjust/AdjustManager.kt index 587706f..c60faee 100644 --- a/StatisticReporter/src/main/java/com/gamedog/statisticreporter/adjust/AdjustManager.kt +++ b/StatisticReporter/src/main/java/com/gamedog/statisticreporter/adjust/AdjustManager.kt @@ -1,16 +1,21 @@ package com.gamedog.statisticreporter.adjust -import android.util.Log + +import android.os.Handler +import android.os.HandlerThread +import android.text.TextUtils import com.adjust.sdk.Adjust import com.adjust.sdk.AdjustAdRevenue import com.adjust.sdk.AdjustAttribution import com.adjust.sdk.AdjustConfig +import com.adjust.sdk.AdjustEvent import com.adjust.sdk.LogLevel import com.adjust.sdk.OnAttributionChangedListener -import com.adjust.sdk.huawei.BuildConfig import com.ama.core.architecture.BaseApp +import com.ama.core.architecture.util.SpUtil +import com.gamedog.statisticreporter.adjust.AdjustManager.Companion.USER_TYPE_BUY import org.json.JSONException -import org.json.JSONObject + class AdjustManager private constructor() { @@ -23,28 +28,74 @@ class AdjustManager private constructor() { INSTANCE ?: AdjustManager().also { INSTANCE = it } } } + + + const val ATTRI_TYPE_ORGANIC = "Organic" + const val ATTRI_TYPE_UNTRUSTED = "Untrusted Devices" + const val ATTRI_TYPE_GOOGLE = "Google Organic Search" + + const val USER_TYPE_NORMAL = 1 + const val USER_TYPE_BUY = 2 } private val mAppContext = BaseApp.appContext() + private val mSpHelper = SpHelper() + private val mUserFromCheckRunnable = kotlinx.coroutines.Runnable { + run { + // 所有用户一开始都是自然用户的状态,需要通过调用setOnAttributionChangedListener这个方法(这个方法就是返回用户改变后的状态),获得买量来源信息 + Adjust.getAttribution { attribution -> + val networkFrom = attribution.network + var userTypeInt = 0 + if (!TextUtils.isEmpty(networkFrom)) { + if (networkFrom.contains(ATTRI_TYPE_GOOGLE) || networkFrom.contains(ATTRI_TYPE_UNTRUSTED)) { + userTypeInt = USER_TYPE_NORMAL + } else if (!networkFrom.contains(ATTRI_TYPE_ORGANIC)) { + userTypeInt = USER_TYPE_BUY + } + } + + if (userTypeInt > 0) { + mSpHelper.saveUserType(userTypeInt) + mChecker.stopPolling() + } + } + } + } + private val mChecker: PollCheckHelper = PollCheckHelper(180, + 3, mUserFromCheckRunnable, { + mSpHelper.saveUserType(USER_TYPE_NORMAL) + }) fun initSdk(appToken: String) { - val isDebug = BuildConfig.DEBUG + val isDebug = true val environment = if (isDebug) AdjustConfig.ENVIRONMENT_SANDBOX else AdjustConfig.ENVIRONMENT_PRODUCTION val config = AdjustConfig(mAppContext, appToken, environment).apply { setLogLevel(if (isDebug) LogLevel.VERBOSE else LogLevel.WARN) enableSendingInBackground() enableCoppaCompliance() + enableCostDataInAttribution() onAttributionChangedListener = OnAttributionChangedListener { handleAttributionEvent(it) } + mChecker.startPolling() } Adjust.initSdk(config) Adjust.enable() } + /** + * val event = AdjustEvent("g3mfiw") + * event.setCallbackId("f2e728d8-271b-49ab-80ea-27830a215147") + */ + fun reportAdjustEvent(event: AdjustEvent, callbackId: String?) { + callbackId?.let { + event.callbackId = callbackId + } + Adjust.trackEvent(event) + } fun reportAdRevenueInfo() { @@ -68,20 +119,101 @@ class AdjustManager private constructor() { } + fun isUserBuy(): Boolean { + return mSpHelper.isUserBuy() + } //----------------------- PRIVATE ------------------------// - private fun handleAttributionEvent(attribution: AdjustAttribution): JSONObject? { + private fun handleAttributionEvent(attribution: AdjustAttribution) { try { - return JSONObject(attribution.fbInstallReferrer) + if (mSpHelper.hasIdentityUserType()) { + return + } + mChecker.startPolling() } catch (e: JSONException) { - Log.d("example", e.message!!) + e.printStackTrace() } - return null + } + + + + + +} + + + +class SpHelper { + companion object { + const val KEY_USER_FROM_TYPE = "KEY_USER_FROM_TYPE" // 1:自然用户 2:买量用户 + } + + private var mUserType = SpUtil.instance().getInt(KEY_USER_FROM_TYPE) + + fun hasIdentityUserType(): Boolean { + return mUserType > 0 + } + + fun saveUserType(userType: Int) { + mUserType = userType + SpUtil.instance().putInt(KEY_USER_FROM_TYPE, mUserType) + } + + fun isUserBuy(): Boolean { + return mUserType == USER_TYPE_BUY } } + +class PollCheckHelper(private val mTotalCheckSec: Int, + private val mTotalCheckGapSec: Int, + private val mCheckRunnable: Runnable, + private val mFinishCallback: ()->Unit) { + + private var handlerThread: HandlerThread? = null + private var handler: Handler? = null + private var mStartMs: Long = 0L + private var mPollRunnable: Runnable? = null + private var mHasStop = false + private var mHasStarted = false + + + fun startPolling() { + if (mHasStarted) { + return + } + handlerThread = HandlerThread("PollingThread").apply { start() } + handler = Handler(handlerThread!!.looper) + mStartMs = System.currentTimeMillis() + + mPollRunnable = Runnable { + mCheckRunnable.run() + val hasExpired = System.currentTimeMillis() - mStartMs >= mTotalCheckSec * 1000 + if (hasExpired || mHasStop) { + stopPolling() + if (hasExpired) { + mFinishCallback.invoke() + } + } else { + handler?.postDelayed(mPollRunnable!!, mTotalCheckGapSec * 1000L) + } + } + handler?.post(mPollRunnable!!) + mHasStarted = true + } + + fun stopPolling() { + mHasStop = true + mPollRunnable?.let { + handler?.removeCallbacks(it) + } + handlerThread?.quitSafely() + mPollRunnable = null + } + +} \ No newline at end of file