Commit 4dd8ba46 authored by wanglei's avatar wanglei

...

parent de9432a7
......@@ -66,4 +66,30 @@ dependencies {
//第三方UI控件
implementation("io.github.cymchad:BaseRecyclerViewAdapterHelper4:4.1.4")
//firebase
implementation(platform("com.google.firebase:firebase-bom:32.3.1"))
implementation("com.google.firebase:firebase-messaging")
implementation("com.google.firebase:firebase-analytics-ktx")
implementation("com.google.firebase:firebase-crashlytics")
implementation("com.google.firebase:firebase-config")
//facebook
implementation("com.facebook.android:facebook-android-sdk:[8,9)")
//广告
//admob渠道
implementation(libs.vungle)
implementation(libs.facebook)
implementation(libs.mintegral)
implementation(libs.pangle)
//applovin sdk
implementation(libs.applovin)
//applovin渠道
implementation(libs.applovin.google)
implementation(libs.applovin.admob)
implementation(libs.applovin.facebook) //meta
implementation(libs.applovin.mintegral)//mintegral
implementation(libs.applovin.pangle) //pangle
implementation(libs.applovin.vungle) //vungle
}
\ No newline at end of file
......@@ -73,7 +73,7 @@ class MyApplication : Application() {
private fun initApp() {
//初始化广告相关业务
// AdsMgr.init(appContext)
// com.base.appzxhy.ads.AdsMgr.init(appContext)
// FacebookSdk.sdkInitialize(applicationContext)
// val token = AppPreferences.getInstance().getString("token", "")
......@@ -189,18 +189,18 @@ class MyApplication : Application() {
private fun initConfig(config: String? = AppPreferences.getInstance().getString("config", "")) {
// kotlin.runCatching {
// val configBean = Gson().fromJson(config, ConfigBean::class.java)
// val configBean = Gson().fromJson(config, com.base.appzxhy.bean.config.ConfigBean::class.java)
//
// val jsonObject = JSONObject()
// jsonObject.put("ut", configBean.ut)
// EventUtils.event("user_type", ext = jsonObject)
//
// //配置
// ConfigBean.configBean = configBean
// com.base.appzxhy.bean.config.ConfigBean.configBean = configBean
//
// //广告
// AdsMgr.adsConfigBean = configBean.adConfigBean
// com.base.localweatherwhite.utils.LogEx.logDebug("initConfig", "AdsMgr.adsConfigBean=${configBean.adConfigBean.functionInShowAd}")
// com.base.appzxhy.ads.AdsMgr.adsConfigBean = configBean.adConfigBean
// com.base.localweatherwhite.utils.LogEx.logDebug("initConfig", "com.base.appzxhy.ads.AdsMgr.adsConfigBean=${configBean.adConfigBean.functionInShowAd}")
//
// //通知
// PopupConstObject.popupConfigBean = configBean.popupConfigBean
......
package com.base.appzxhy.ads
import com.base.appzxhy.BuildConfig
/**
* 部分常量配置相关,如admob广告位id与通知渠道等
*/
object AdConstConfig {
//用于替换admob广告位,区分debug与正式广告位id
inline val ADMOB_OPEN_UNIT_ID get() = if (BuildConfig.DEBUG) OPEN_ADMOB_ID_TEST else OPEN_ADMOB_ID
inline val ADMOB_BANNER_UNIT_ID get() = if (BuildConfig.DEBUG) BANNER_ADMOB_ID_TEST else BANNER_ADMOB_ID
inline val ADMOB_INSERT_UNIT_ID get() = if (BuildConfig.DEBUG) INTER_ADMOB_ID_TEST else INTER_ADMOB_ID
inline val ADMOB_NATIVE_UNIT_ID get() = if (BuildConfig.DEBUG) NATIVE_ADMOB_ID_TEST else NATIVE_ADMOB_ID
//admob test id
const val OPEN_ADMOB_ID_TEST = "ca-app-pub-3940256099942544/9257395921"
const val INTER_ADMOB_ID_TEST = "ca-app-pub-3940256099942544/1033173712"
const val NATIVE_ADMOB_ID_TEST = "ca-app-pub-3940256099942544/2247696110"
const val BANNER_ADMOB_ID_TEST = "ca-app-pub-3940256099942544/9214589741"
// admob广告id
const val OPEN_ADMOB_ID = "ca-app-pub-3940256099942544/9257395921"
const val INTER_ADMOB_ID = "ca-app-pub-3940256099942544/1033173712"
const val NATIVE_ADMOB_ID = "ca-app-pub-3940256099942544/2247696110"
const val BANNER_ADMOB_ID = "ca-app-pub-3940256099942544/9214589741"
const val MAX_SDK_KEY =
"GGPreND6SRmCt1zJgn5faiLGD8c2PVGPLgPpSg7cHanVTud1DhtuI9MmteTqlEviaJ57WnxW68kQDaATJ5z3cW"
const val MAX_OPEN_UNIT_ID = "d1d943cdd3127c90"
const val MAX_INSERT_UNIT_ID = "b31e7f6d11ee659e"
const val MAX_BANNER_UNIT_ID = "ca-app-pub-3940256099942544/9214589741"
const val MAX_NATIVE_UNIT_ID = "96e8fe78b0efc5d1"
}
\ No newline at end of file
package com.base.appzxhy.ads
import android.animation.ObjectAnimator
import android.animation.ValueAnimator.INFINITE
import android.app.AlertDialog
import android.content.Context
import android.view.LayoutInflater
import android.view.animation.LinearInterpolator
import com.base.appzxhy.databinding.DialogAdPreparingBinding
import com.base.appzxhy.utils.DensityUtils
import com.base.appzxhy.utils.LogEx
object AdDialog {
private val TAG = "com.base.appzxhy.ads.AdDialog"
fun Context.showAdPreparingDialog(where: Int = 0): AlertDialog {
LogEx.logDebug(TAG, "where=$where")
val binding = DialogAdPreparingBinding.inflate(LayoutInflater.from(this))
val dialog = AlertDialog.Builder(this).create()
dialog.setView(binding.root)
dialog.setCancelable(false)
dialog.setCanceledOnTouchOutside(false)
dialog.show()
val params = dialog.window?.attributes
params?.width = DensityUtils.dip2px(200f)
params?.height = DensityUtils.dip2px(146f)
dialog.window?.attributes = params
dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
// 创建一个旋转动画
val rotateAnimator = ObjectAnimator.ofFloat(binding.iv, "rotation", 0f, -360f)
rotateAnimator.setDuration(1000) // 设置动画持续时间为1000毫秒
rotateAnimator.repeatCount = INFINITE
rotateAnimator.interpolator = LinearInterpolator() // 设置插值器为线性插值
rotateAnimator.start()
return dialog
}
}
\ No newline at end of file
package com.base.appzxhy.ads
import com.base.appzxhy.MyApplication
import com.base.appzxhy.helper.EventUtils
import com.base.appzxhy.utils.LogEx
import org.json.JSONObject
import java.util.UUID
val taichiPref by lazy {
MyApplication.appContext.getSharedPreferences("TaichiTroasCache", 0)
}
val taichiSharedPreferencesEditor by lazy {
taichiPref.edit()
}
abstract class AdEvent {
abstract val TAG: String
var adUnit: String = ""
var from: String = ""
val reqId = UUID.randomUUID().toString()
fun adPrepareShow() {
val obj1 = JSONObject()
obj1.put("ad_unit", adUnit)
obj1.put("req_id", reqId)
obj1.put("from", from)
EventUtils.event("ad_prepare_show", ext = obj1)
LogEx.logDebug(TAG, "ad_prepare_show $obj1")
}
fun adPulStart() {
val obj = JSONObject()
obj.put("req_id", reqId)
obj.put("ad_unit", adUnit)
obj.put("ad_type", adUnit)
obj.put("from", from)
EventUtils.event("ad_pull_start", ext = obj)
LogEx.logDebug(TAG, "ad_pull_start $obj")
}
fun adShowError(reason: Any) {
val obj = JSONObject()
obj.put("ad_unit", adUnit)
obj.put("req_id", reqId)
obj.put("from", from)
obj.put("reason", reason.toString())
EventUtils.event("ad_show_error", ext = obj)
LogEx.logDebug(TAG, "ad_show_error $obj")
}
fun adLimited(value: String) {
val obj = JSONObject()
obj.put("ad_unit", adUnit)
obj.put("req_id", reqId)
obj.put("from", from)
EventUtils.event("ad_limit", value, obj)
LogEx.logDebug(TAG, "ad_limit $obj")
}
}
\ No newline at end of file
package com.base.appzxhy.ads
import android.app.Activity
import android.content.Context
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import com.applovin.sdk.AppLovinMediationProvider
import com.applovin.sdk.AppLovinSdk
import com.applovin.sdk.AppLovinSdkInitializationConfiguration
import com.base.appzxhy.BuildConfig
import com.base.appzxhy.ads.admob.AdBannerMgr
import com.base.appzxhy.ads.admob.AdInsertMgr
import com.base.appzxhy.ads.admob.AdNativeMgr
import com.base.appzxhy.ads.admob.AdOpenMgr
import com.base.appzxhy.ads.admob.AdmobEvent
import com.base.appzxhy.ads.applovin.AdMaxEvent
import com.base.appzxhy.ads.applovin.MaxInsertMgr
import com.base.appzxhy.ads.applovin.MaxNativeMgr
import com.base.appzxhy.ads.applovin.MaxOpenMgr
import com.base.appzxhy.bean.config.AdConfigBean
import com.base.appzxhy.bean.config.ConfigBean.Companion.configBean
import com.base.appzxhy.helper.EventUtils
import com.base.appzxhy.utils.AppPreferences
import com.base.appzxhy.utils.LogEx
import com.base.appzxhy.utils.ToastUtils.toast
import com.google.android.gms.ads.MobileAds
import com.google.android.gms.ads.identifier.AdvertisingIdClient
import com.google.android.gms.ads.initialization.AdapterStatus
import java.util.Collections
import java.util.concurrent.Executors
/**
* 广告管理类
*/
object AdsMgr {
private val adOpenMgr by lazy {
AdOpenMgr()
}
private val adInsertMgr by lazy {
AdInsertMgr()
}
private val adNativeMgr by lazy {
AdNativeMgr()
}
private val adBannerMgr by lazy {
AdBannerMgr()
}
private val maxOpenMgr by lazy {
MaxOpenMgr()
}
private val maxInsertMgr by lazy {
MaxInsertMgr()
}
private val maxNativeMgr by lazy {
MaxNativeMgr()
}
/**
* 是否初始化
*/
var isAdmobInit = false
private set
/**
* 是否初始化
*/
var isMaxInit = false
private set
/**
* 广告配置项目
*/
var adsConfigBean: AdConfigBean = AdConfigBean()
/**
* Init 初始化
*
* @param context 这里最好是appContext,因为是耗时操作,等它初始化完毕马上加载开屏和插屏广告
*/
fun init(context: Context) {
if (configBean.isInBlackList) {
EventUtils.event("isInBlackList", configBean.isInBlackList.toString())
return
}
initAdmob(context)
initMax(context)
}
private fun initAdmob(context: Context) {
MobileAds.initialize(context) {
val readyAdapter = it.adapterStatusMap.entries.find { entry ->
entry.value.initializationState == AdapterStatus.State.READY
}
isAdmobInit = readyAdapter != null
EventUtils.event("AdmobInit", "AdmobInit")
// context.toast("admob init")
if (adsConfigBean.adSwitch) {
admobInitCallBack?.invoke()
admobInitCallBack = null
adOpenMgr.loadAd(context, false, AdmobEvent("openAd", context::class.java.simpleName))
adInsertMgr.loadAd(context, false, AdmobEvent("interAd", context::class.java.simpleName))
}
}
}
private fun initMax(context: Context) = kotlin.runCatching {
val executor = Executors.newSingleThreadExecutor()
executor.execute {
val currentGaid = AdvertisingIdClient.getAdvertisingIdInfo(context).id
AppPreferences.getInstance().getString("gid", currentGaid)
val build = AppLovinSdkInitializationConfiguration
.builder(AdConstConfig.MAX_SDK_KEY, context)
build.setMediationProvider(AppLovinMediationProvider.MAX)
if (BuildConfig.DEBUG) {
build.testDeviceAdvertisingIds = Collections.singletonList(currentGaid)
}
val initConfig = build.build()
runCatching {
AppLovinSdk.getInstance(context).initialize(initConfig) {
isMaxInit = true
// maxOpenMgr.loadAd(context)
if (!adsConfigBean.adSwitch) {
maxInsertMgr.loadAd(context, false, AdMaxEvent("interAd", context::class.java.simpleName))
context.toast("max init")
maxInitCallBack?.invoke()
maxInitCallBack = null
}
}
}
}
}
private var admobInitCallBack: (() -> Unit)? = null
private var maxInitCallBack: (() -> Unit)? = null
/**
* 展示开屏广告
*
* @param activity 当前页面
* @param showCallBack 展示回调
*/
fun showOpen(
activity: Activity,
isUnLimit: Boolean = false,
showCallBack: AdsShowCallBack? = null,
) {
if (configBean.isInBlackList) {
EventUtils.event("isInBlackList", "isInBlackList=${configBean.isInBlackList}")
return
}
val from = activity::class.java.simpleName
if (adsConfigBean.adSwitch) {
if (isAdmobInit) {
adOpenMgr.show(activity, isUnLimit, AdmobEvent("openAd", from), showCallBack)
} else {
admobInitCallBack = {
}
adOpenMgr.show(activity, isUnLimit, AdmobEvent("openAd", from), showCallBack)
}
} else {
if (isMaxInit) {
maxOpenMgr.show(activity, isUnLimit, AdMaxEvent("openAd", from), showCallBack)
} else {
maxInitCallBack = {
maxOpenMgr.show(activity, isUnLimit, AdMaxEvent("openAd", from), showCallBack)
}
}
}
}
/**
* 展示插屏广告
*
* @param activity 当前页面
* @param showCallBack 展示回调
* @param isUnLimit 是否不受限制 默认false 代表受到限制
*/
fun showInsert(
activity: Activity,
isUnLimit: Boolean = false,
showCallBack: AdsShowCallBack? = null,
) {
if (configBean.isInBlackList) {
EventUtils.event("isInBlackList", configBean.isInBlackList.toString())
return
}
LogEx.logDebug("showAd", "adSwitch=${adsConfigBean.adSwitch}")
val from = activity::class.java.simpleName
if (adsConfigBean.adSwitch) {
adInsertMgr.show(activity, isUnLimit, AdmobEvent("interAd", from), showCallBack)
} else {
maxInsertMgr.show(activity, isUnLimit, AdMaxEvent("interAd", from), showCallBack)
}
}
/**
* 展示原生广告
*
* @param nativeView 需要展示广告的布局容器
* @param layout 原生广告布局 ,这里传入的layout要和com.example.mydemo.strategy.ads.admob.NativeView里的id一致
*/
fun showNative(
nativeView: NativeParentView,
@LayoutRes layout: Int,
nativeCallBack: ((Any?) -> Unit)? = null
) {
if (configBean.isInBlackList) {
EventUtils.event("isInBlackList", configBean.isInBlackList.toString())
return
}
if (!isAdmobInit) return
if (adsConfigBean.adSwitch) {
adNativeMgr.show(AdmobEvent("nativeAd", "nativeAd"), nativeView, layout, nativeCallBack)
} else {
maxNativeMgr.show(AdMaxEvent("nativeAd", "nativeAd"), nativeView, layout, nativeCallBack)
}
}
fun isNativeShow() = (isAdmobInit && !configBean.isInBlackList) && LimitUtils.isAdShow(AdsType.NATIVE, null)
/**
* 展示banner广告
*
* @param parent 展示广告的父布局容器
*/
fun showBanner(parent: ViewGroup, collapsible: Boolean = true, adClose: (() -> Unit)? = null) {
if (configBean.isInBlackList) {
EventUtils.event("isInBlackList", configBean.isInBlackList.toString())
return
}
if (adsConfigBean.adSwitch) {
adBannerMgr.show(parent, collapsible, adClose)
}
}
}
\ No newline at end of file
package com.base.appzxhy.ads
abstract class AdsShowCallBack {
open fun show() {}
abstract fun close(where: Int = 0)
abstract fun failed(where: Int = 0)
abstract fun googleFailed(where: Int = 0)
}
\ No newline at end of file
package com.base.appzxhy.ads
/**
* 广告类型
* 0=开屏广告、1=插屏广告、2=原生广告、3=Banner横幅广告
*/
@JvmInline
value class AdsType private constructor(val value: Int) {
companion object {
val OPEN = AdsType(0)
val INSERT = AdsType(1)
val NATIVE = AdsType(2)
val BANNER = AdsType(3)
fun from(adsType: Int): AdsType {
return when (adsType) {
OPEN.value -> OPEN
INSERT.value -> INSERT
NATIVE.value -> NATIVE
else -> BANNER
}
}
}
}
\ No newline at end of file
package com.base.appzxhy.ads
import android.app.Activity
import android.app.Dialog
import android.content.Context
import java.lang.ref.WeakReference
class adState<T>() {
var adDialog: Dialog? = null
/**
* 当前缓存的广告
*/
var currentAd: T? = null
/**
* 是否正在缓存加载广告
*/
var loadingAd: Boolean = false
/**
* 是否正在显示广告
*/
var showingAd: Boolean = false
/**
* 用于保存引用现有页面,在此页面显示广告(因为要等待广告加载完毕)
*/
var activityRef: WeakReference<Activity>? = null
/**
* 上一次的缓存成功时间
*/
var lastLoadTime: Long = 0
/**
* 上次展示时间
*/
var lastShowTime: Long = 0
fun onAdDisplayed() {
showingAd = true
adDialog?.dismiss()
adDialog = null
lastShowTime = System.currentTimeMillis()
currentAd = null
activityRef = null
}
fun onAdHidden() {
// 广告关闭,清空缓存数据,重新加载
showingAd = false
}
fun onAdDisplayFailed() {
adDialog?.dismiss()
adDialog = null
showingAd = false
currentAd = null
activityRef = null
}
fun onAdLoaded(ad: T?) {
//这里可能提前设置,所有可以不设置,max回调的类型可能不同
if (ad != null) {
currentAd = ad
}
loadingAd = false
lastLoadTime = System.currentTimeMillis()
}
fun onAdLoadFailed() {
adDialog?.dismiss()
adDialog = null
loadingAd = false
}
}
/**
* 特定广告管理基类
* @param T 缓存广告的类
*/
abstract class BaseAdMgr<T> {
/**
* 广告展示回调
*/
protected var showCallBack: AdsShowCallBack? = null
/**
* 当前缓存的广告
*/
protected var currentAd: T? = null
/**
* 是否正在缓存加载广告
*/
protected var loadingAd: Boolean = false
/**
* 是否正在显示广告
*/
protected var showingAd: Boolean = false
/**
* 用于保存引用现有页面,在此页面显示广告(因为要等待广告加载完毕)
*/
protected var activityRef: WeakReference<Activity>? = null
/**
* 上一次的缓存成功时间
*/
protected var lastLoadTime: Long = 0
/**
* 预加载广告
*
* @param context 加载所用的上下文,一般使用appContext
*/
abstract fun loadAd(context: Context, isUnLimit: Boolean = true, adEvent: AdEvent)
/**
* 广告显示
*
* @param activity 当前页面
*/
abstract fun show(activity: Activity, isUnLimit: Boolean = true, adEvent: AdEvent, showCallBack: AdsShowCallBack? = null)
/**
* 预加载的缓存超时判断
*
* @return true:没有超时 false:超时需要重新加载
*/
abstract fun adAvailable(): Boolean
}
\ No newline at end of file
package com.base.appzxhy.ads
import com.base.appzxhy.utils.AppPreferences
import com.base.appzxhy.utils.KotlinExt.toFormatTime4
/**
* 控制广告计数与判断显示条件
*
*/
object LimitUtils {
const val NUM_DISPLAY = "local_numDisplayLimit"
const val NUM_REQUEST = "local_numRequestLimit"
const val NUM_CLICK = "local_numClickLimit"
const val SAVE_DATE = "local_SAVE_DATE"
/**
* 保存的时间,用来判断是否是当天,不是当天要重置计数次数
*/
private var saveDate
get() = AppPreferences.getInstance()
.getString(SAVE_DATE, System.currentTimeMillis().toFormatTime4())
set(value) = AppPreferences.getInstance().put(SAVE_DATE, value)
/**
* 广告请求是否到达限制
*/
private inline val isRequestLimited: Boolean
get() {
val maxCount = AdsMgr.adsConfigBean.numRequestLimit
return maxCount > -1 && AppPreferences.getInstance()
.getInt(NUM_REQUEST, 0) >= maxCount
}
/**
* 广告展示是否到达限制
*/
private inline val isDisplayLimited: Boolean
get() {
val maxCount = AdsMgr.adsConfigBean.numDisplayLimit
return maxCount > -1 && AppPreferences.getInstance()
.getInt(NUM_DISPLAY, 0) >= maxCount
}
/**
* 广告点击是否到达限制
*/
private inline val isClickLimited: Boolean
get() {
val maxCount = AdsMgr.adsConfigBean.numClickLimit
return maxCount > -1 && AppPreferences.getInstance()
.getInt(NUM_CLICK, 0) >= maxCount
}
private fun getAdEventMsg(adsType: AdsType): String {
return when (adsType) {
AdsType.OPEN -> "Open"
AdsType.INSERT -> "Inter"
AdsType.NATIVE -> "Native"
else -> "Banner"
}
}
/**
* 是否显示广告
*
* @return true or false
*/
fun isAdShow(adsType: AdsType, adEvent: AdEvent?): Boolean {
val currentDate = System.currentTimeMillis().toFormatTime4()
if (saveDate != currentDate) {
//如果已经不是今天了,就重置个数
saveDate = currentDate
AppPreferences.getInstance().put(NUM_DISPLAY, 0)
AppPreferences.getInstance().put(NUM_REQUEST, 0)
AppPreferences.getInstance().put(NUM_CLICK, 0)
}
if (isDisplayLimited) {
val value = "current${getAdEventMsg(adsType)} " +
"show=${AppPreferences.getInstance().getInt(NUM_DISPLAY, 0)} " +
"${getAdEventMsg(adsType).lowercase()}_" + "max_show=${AdsMgr.adsConfigBean.numDisplayLimit}"
adEvent?.adLimited(value)
}
if (isClickLimited) {
val value =
"current${getAdEventMsg(adsType)}Click=${AppPreferences.getInstance().getInt(NUM_CLICK, 0)} "
"${getAdEventMsg(adsType).lowercase()}_max_click=${AdsMgr.adsConfigBean.numClickLimit}"
adEvent?.adLimited(value)
}
if (isRequestLimited) {
val value = "current${getAdEventMsg(adsType)}Request=${AppPreferences.getInstance().getInt(NUM_REQUEST, 0)} " +
"${getAdEventMsg(adsType).lowercase()}_max_request=${AdsMgr.adsConfigBean.numRequestLimit}"
adEvent?.adLimited(value)
}
return !(isDisplayLimited || isClickLimited || isRequestLimited)
}
private fun addNum(key: String) {
val currentDate = System.currentTimeMillis().toFormatTime4()
if (saveDate != currentDate) {
//如果已经不是今天了,就重置个数
saveDate = currentDate
AppPreferences.getInstance().put(key, 1)
return
}
AppPreferences.getInstance()
.put(key, (AppPreferences.getInstance().getInt(key, 0) + 1))
}
fun addDisplayNum() {
addNum(NUM_DISPLAY)
}
fun addRequestNum() {
addNum(NUM_REQUEST)
}
fun addClickNum() {
addNum(NUM_CLICK)
}
/**
* 开屏和插页广告的显示间隔限制
*
* @param lastTime 上一次显示的时间
*/
fun isIntervalLimited(lastTime: Long, adEvent: AdEvent): Boolean {
val flag = ((System.currentTimeMillis() - lastTime) / 1000).toInt() < (AdsMgr.adsConfigBean.timeInterval)
if (flag) {
adEvent.adShowError("ad in timeInterval")
}
return flag
}
}
\ No newline at end of file
package com.base.appzxhy.ads
import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.LayoutRes
import com.applovin.mediation.MaxAd
import com.applovin.mediation.nativeAds.MaxNativeAdLoader
import com.applovin.mediation.nativeAds.MaxNativeAdView
import com.applovin.mediation.nativeAds.MaxNativeAdViewBinder
import com.base.appzxhy.R
import com.google.android.gms.ads.nativead.NativeAd
import com.google.android.gms.ads.nativead.NativeAdView
@SuppressLint("ViewConstructor")
class NativeParentView(context: Context, attrs: AttributeSet? = null) :
FrameLayout(context, attrs) {
fun setNativeAd(
nativeAd: NativeAd,
@LayoutRes resource: Int? = null
) {
val layout = resource ?: R.layout.layout_admob_native_custom
val adView =
layout.let { LayoutInflater.from(context).inflate(it, null) } as NativeAdView
adView.mediaView = adView.findViewById(R.id.ad_media)
adView.headlineView = adView.findViewById(R.id.ad_headline)
adView.bodyView = adView.findViewById(R.id.ad_body)
adView.callToActionView = adView.findViewById(R.id.ad_call_to_action)
adView.iconView = adView.findViewById(R.id.ad_app_icon)
(adView.headlineView as TextView?)?.text = nativeAd.headline
adView.mediaView?.mediaContent = nativeAd.mediaContent
if (nativeAd.body == null) {
adView.bodyView?.visibility = View.INVISIBLE
} else {
adView.bodyView?.visibility = View.VISIBLE
(adView.bodyView as TextView?)?.text = nativeAd.body
}
if (nativeAd.callToAction == null) {
adView.callToActionView?.visibility = View.INVISIBLE
} else {
adView.callToActionView?.visibility = View.VISIBLE
(adView.callToActionView as Button?)?.text = nativeAd.callToAction
}
if (nativeAd.icon == null) {
adView.iconView?.visibility = View.GONE
} else {
(adView.iconView as ImageView?)?.setImageDrawable(
nativeAd.icon?.drawable
)
adView.iconView?.visibility = View.VISIBLE
}
adView.setNativeAd(nativeAd)
setBackgroundResource(0)
removeAllViews()
addView(adView)
}
fun setNativeAd(
nativeAdLoader: MaxNativeAdLoader,
nativeAd: MaxAd,
@LayoutRes resource: Int? = null
) {
val layout = resource ?: R.layout.layout_max_native_custom
val binder: MaxNativeAdViewBinder =
MaxNativeAdViewBinder.Builder(layout)
.setTitleTextViewId(R.id.title_text_view)
.setBodyTextViewId(R.id.body_text_view)
.setAdvertiserTextViewId(R.id.advertiser_text_view)
.setIconImageViewId(R.id.icon_image_view)
.setMediaContentViewGroupId(R.id.media_view_container)
.setOptionsContentViewGroupId(R.id.options_view)
.setStarRatingContentViewGroupId(R.id.star_rating_view)
.setCallToActionButtonId(R.id.cta_button)
.build()
val adView = MaxNativeAdView(binder, context)
nativeAdLoader.render(adView, nativeAd)
setBackgroundResource(0)
removeAllViews()
addView(adView)
}
}
@SuppressLint("ViewConstructor")
class CustomParentNativeView(context: Context, val layout: Int, attrs: AttributeSet? = null) :
FrameLayout(context, attrs) {
init {
layoutParams =
LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}
fun setNativeAd(nativeAd: NativeAd?) {
nativeAd ?: return
val adView = LayoutInflater.from(context)
.inflate(layout, this, false) as NativeAdView
adView.mediaView = adView.findViewById(R.id.ad_media)
adView.headlineView = adView.findViewById(R.id.ad_headline)
adView.bodyView = adView.findViewById(R.id.ad_body)
adView.callToActionView = adView.findViewById(R.id.ad_call_to_action)
adView.iconView = adView.findViewById(R.id.ad_app_icon)
(adView.headlineView as TextView?)?.text = nativeAd.headline
adView.mediaView!!.mediaContent = nativeAd.mediaContent
if (nativeAd.body == null) {
adView.bodyView!!.visibility = INVISIBLE
} else {
adView.bodyView!!.visibility = VISIBLE
(adView.bodyView as TextView?)?.text = nativeAd.body
}
if (nativeAd.callToAction == null) {
adView.callToActionView!!.visibility = INVISIBLE
} else {
adView.callToActionView!!.visibility = VISIBLE
(adView.callToActionView as Button?)?.text = nativeAd.callToAction
}
if (nativeAd.icon == null) {
adView.iconView!!.visibility = GONE
} else {
(adView.iconView as ImageView?)?.setImageDrawable(
nativeAd.icon!!.drawable
)
adView.iconView!!.visibility = VISIBLE
}
adView.setNativeAd(nativeAd)
removeAllViews()
addView(adView)
}
}
\ No newline at end of file
package com.base.appzxhy.ads.admob
import android.os.Bundle
import android.view.ViewGroup
import android.view.ViewTreeObserver
import com.base.appzxhy.ads.AdsMgr
import com.base.appzxhy.ads.AdsType
import com.base.appzxhy.ads.AdConstConfig
import com.base.appzxhy.ads.LimitUtils
import com.google.ads.mediation.admob.AdMobAdapter
import com.google.android.gms.ads.AdListener
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.AdSize
import com.google.android.gms.ads.AdView
import com.google.android.gms.ads.LoadAdError
import java.util.UUID
/**
*banner广告加载显示管理类
*/
class AdBannerMgr {
private var adView: AdView? = null
private var listener: ViewTreeObserver.OnGlobalLayoutListener? = null
fun show(parent: ViewGroup, collapsible: Boolean, adClose: (() -> Unit)? = null) {
if (!AdsMgr.adsConfigBean.adSwitch) {
return
}
val admobEvent = AdmobEvent("banner", "banner")
if (!LimitUtils.isAdShow(AdsType.BANNER, admobEvent)) {
adView = null
return
}
parent.removeAllViews()
adView?.destroy()
adView = null
adView = AdView(parent.context)
parent.addView(adView)
adView?.onPaidEventListener = AdmobEvent.EventOnPaidEventListener(adView)
listener = ViewTreeObserver.OnGlobalLayoutListener {
val screenPixelDensity = parent.context.resources.displayMetrics.density
val adWidth = (parent.width / screenPixelDensity).toInt()
val adSize =
AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(parent.context, adWidth)
adView?.adUnitId = AdConstConfig.ADMOB_BANNER_UNIT_ID
adView?.setAdSize(adSize)
loadAd(admobEvent, collapsible, adClose)
parent.viewTreeObserver.removeOnGlobalLayoutListener(listener)
}
parent.viewTreeObserver.addOnGlobalLayoutListener(listener)
}
fun loadAd(admobEvent: AdmobEvent, collapsible: Boolean, adClose: (() -> Unit)?) {
val build = AdRequest.Builder()
if (collapsible) {
val extras = Bundle()
extras.putString("collapsible", "bottom")
extras.putString("collapsible_request_id", UUID.randomUUID().toString())
build.addNetworkExtrasBundle(AdMobAdapter::class.java, extras)
}
val adRequest = build.build()
adView?.adListener =
object : AdListener() {
override fun onAdFailedToLoad(loadAdError: LoadAdError) {
super.onAdFailedToLoad(loadAdError)
admobEvent.pullAd(loadAdError.responseInfo, loadAdError)
}
override fun onAdLoaded() {
admobEvent.pullAd(adView?.responseInfo)
}
override fun onAdOpened() {
}
override fun onAdClosed() {
super.onAdClosed()
adClose?.invoke()
}
}
adView?.loadAd(adRequest)
}
}
\ No newline at end of file
package com.base.appzxhy.ads.admob
import android.app.Activity
import android.content.Context
import com.base.appzxhy.ads.AdConstConfig.ADMOB_INSERT_UNIT_ID
import com.base.appzxhy.ads.AdDialog.showAdPreparingDialog
import com.base.appzxhy.ads.AdEvent
import com.base.appzxhy.ads.AdsShowCallBack
import com.base.appzxhy.ads.AdsType
import com.base.appzxhy.ads.LimitUtils
import com.base.appzxhy.ads.adState
import com.google.android.gms.ads.AdError
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.FullScreenContentCallback
import com.google.android.gms.ads.LoadAdError
import com.google.android.gms.ads.interstitial.InterstitialAd
import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback
import java.lang.ref.WeakReference
/**
*插屏广告加载显示管理类
*/
class AdInsertMgr {
private var adState = adState<InterstitialAd>()
private var showCallBack: AdsShowCallBack? = null
fun show(activity: Activity, isUnLimit: Boolean, adEvent: AdEvent, showCallBack: AdsShowCallBack?) {
if (activity.isFinishing || activity.isDestroyed) {
showCallBack?.failed(0)
return
}
if (adState.showingAd) {
showCallBack?.failed(1)
return
}
if (showCallBack != null) {
this.showCallBack = showCallBack
adState.activityRef = WeakReference(activity)
if (adState.adDialog == null) {
adState.adDialog = activity.showAdPreparingDialog(1)
}
adEvent.adPrepareShow()
}
if (!adState.loadingAd) {
if (!isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.INSERT, adEvent)) {
showCallBack?.failed(2)
return
}
if (LimitUtils.isIntervalLimited(adState.lastShowTime, adEvent)) {
showCallBack?.failed(3)
return
}
}
if (adState.currentAd == null) {
loadAd(activity, isUnLimit, adEvent)
return
}
if (!adAvailable()) {
loadAd(activity, isUnLimit, adEvent)
return
}
showReadyAd(adEvent, activity)
}
}
private fun showReadyAd(adEvent: AdEvent, activity: Activity) {
adState.currentAd?.run {
fullScreenContentCallback = object : FullScreenContentCallback() {
override fun onAdShowedFullScreenContent() {
super.onAdShowedFullScreenContent()
adState.onAdDisplayed()
showCallBack?.show()
(adEvent as AdmobEvent).showAd(responseInfo, activity)
LimitUtils.addDisplayNum()
}
override fun onAdFailedToShowFullScreenContent(adError: AdError) {
super.onAdFailedToShowFullScreenContent(adError)
adState.onAdDisplayFailed()
showCallBack?.googleFailed()
showCallBack = null
adEvent.adShowError(adError)
}
override fun onAdDismissedFullScreenContent() {
super.onAdDismissedFullScreenContent()
adState.onAdHidden()
showCallBack?.close()
showCallBack = null
loadAd(activity.applicationContext, false, AdmobEvent("interAd", "preload"))
}
override fun onAdClicked() {
super.onAdClicked()
(adEvent as AdmobEvent).clickAd(responseInfo)
//计数
LimitUtils.addClickNum()
}
}
show(activity)
}
}
fun loadAd(context: Context, isUnLimit: Boolean, adEvent: AdEvent) {
if (!isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.INSERT, adEvent)) {
this.showCallBack?.close(4)
this.showCallBack = null
return
}
}
if (!adState.loadingAd) {
adState.loadingAd = true
adEvent.adPulStart()
InterstitialAd.load(context, ADMOB_INSERT_UNIT_ID, AdRequest.Builder().build(),
object : InterstitialAdLoadCallback() {
override fun onAdLoaded(ad: InterstitialAd) {
adState.onAdLoaded(ad)
val ac = adState.activityRef?.get()
if (ac != null) {
show(ac, isUnLimit, adEvent, null)
}
(adEvent as AdmobEvent).pullAd(ad.responseInfo)
LimitUtils.addRequestNum()
ad.onPaidEventListener = AdmobEvent.EventOnPaidEventListener(ad)
}
override fun onAdFailedToLoad(loadAdError: LoadAdError) {
adState.onAdLoadFailed()
(adEvent as AdmobEvent).pullAd(loadAdError.responseInfo, loadAdError)
showCallBack?.googleFailed()
showCallBack = null
}
}
)
}
}
private fun adAvailable() = ((System.currentTimeMillis() - adState.lastLoadTime) / 1000 / 60).toInt() < 30
}
\ No newline at end of file
package com.base.appzxhy.ads.admob
import com.base.appzxhy.ads.AdsType
import com.base.appzxhy.ads.AdConstConfig
import com.base.appzxhy.ads.LimitUtils
import com.base.appzxhy.ads.NativeParentView
import com.google.android.gms.ads.AdListener
import com.google.android.gms.ads.AdLoader
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.LoadAdError
import com.google.android.gms.ads.nativead.NativeAd
import com.google.android.gms.ads.nativead.NativeAdOptions
import java.util.concurrent.ConcurrentLinkedDeque
/**
*原生广告加载显示管理类
*/
class AdNativeMgr {
/**
* 上一次的缓存成功时间
*/
protected var lastTime: Long = 0
/**
* 原生广告缓存队列
*/
private val cacheItems = ConcurrentLinkedDeque<NativeAd>()
private fun loadAd(
admobEvent: AdmobEvent,
parent: NativeParentView,
layout: Int
) {
admobEvent.adPulStart()
if (!LimitUtils.isAdShow(AdsType.NATIVE, admobEvent)) return
var currentNativeAd: NativeAd? = null
val adLoader = AdLoader.Builder(
parent.context,
AdConstConfig.ADMOB_NATIVE_UNIT_ID
).forNativeAd { nativeAd ->
currentNativeAd = nativeAd
cacheItems.offer(nativeAd)
lastTime = System.currentTimeMillis()
nativeAd.setOnPaidEventListener(AdmobEvent.EventOnPaidEventListener(nativeAd))
admobEvent.pullAd(nativeAd.responseInfo)
show(admobEvent, parent, layout)
}.withAdListener(object : AdListener() {
override fun onAdFailedToLoad(error: LoadAdError) {
admobEvent.pullAd(error.responseInfo, error)
}
override fun onAdClicked() {
super.onAdClicked()
admobEvent.clickAd(currentNativeAd?.responseInfo)
}
override fun onAdClosed() {
super.onAdClosed()
}
}).withNativeAdOptions(
NativeAdOptions.Builder()
.build()
).build()
adLoader.loadAds(AdRequest.Builder().build(), 1)
}
fun show(
admobEvent: AdmobEvent,
parent: NativeParentView,
layout: Int,
nativeCallBack: ((Any?) -> Unit)? = null
) {
admobEvent.adPrepareShow()
if (!LimitUtils.isAdShow(AdsType.NATIVE, admobEvent)) {
cacheItems.clear()
return
}
val nativeAd = cacheItems.peek()
if (nativeAd == null || !adAvailable()) {
//缓存过期了就清空
cacheItems.clear()
loadAd(admobEvent, parent, layout)
return
}
nativeCallBack?.invoke(nativeAd)
parent.setNativeAd(nativeAd, layout)
admobEvent.showAd(nativeAd.responseInfo)
}
private fun adAvailable(): Boolean {
return ((System.currentTimeMillis() - lastTime) / 1000 / 60).toInt() < 30
}
}
\ No newline at end of file
package com.base.appzxhy.ads.admob
import android.app.Activity
import android.content.Context
import com.base.appzxhy.ads.AdsType
import com.base.appzxhy.ads.AdConstConfig
import com.base.appzxhy.ads.AdEvent
import com.base.appzxhy.ads.AdsShowCallBack
import com.base.appzxhy.ads.LimitUtils
import com.base.appzxhy.ads.adState
import com.google.android.gms.ads.AdError
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.FullScreenContentCallback
import com.google.android.gms.ads.LoadAdError
import com.google.android.gms.ads.appopen.AppOpenAd
import java.lang.ref.WeakReference
/**
* 开屏广告加载显示管理类
*/
class AdOpenMgr {
private val adState = adState<AppOpenAd>()
private var showCallBack: AdsShowCallBack? = null
fun show(activity: Activity, isUnLimit: Boolean, adEvent: AdEvent, showCallBack: AdsShowCallBack?) {
if (activity.isFinishing || activity.isDestroyed) {
return
}
if (adState.showingAd) {
showCallBack?.failed()
adEvent.adShowError("showingAd")
return
}
if (showCallBack != null) {
this.showCallBack = showCallBack
adState.activityRef = WeakReference(activity)
adEvent.adPrepareShow()
}
if (!adState.loadingAd) {
if (!isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.OPEN, adEvent)) {
showCallBack?.failed()
return
}
if (LimitUtils.isIntervalLimited(adState.lastShowTime, adEvent)) {
showCallBack?.failed()
return
}
}
if (!adAvailable() || adState.currentAd == null) {
loadAd(activity, isUnLimit, adEvent)
return
}
showReadyAd(adEvent, activity)
}
}
private fun showReadyAd(adEvent: AdEvent, activity: Activity) {
adState.currentAd?.run {
fullScreenContentCallback = object : FullScreenContentCallback() {
override fun onAdShowedFullScreenContent() {
showCallBack?.show()
(adEvent as AdmobEvent).showAd(this@run.responseInfo, activity)
adState.onAdDisplayed()
//计数
LimitUtils.addDisplayNum()
}
override fun onAdFailedToShowFullScreenContent(adError: AdError) {
super.onAdFailedToShowFullScreenContent(adError)
showCallBack?.googleFailed()
showCallBack = null
adState.onAdDisplayed()
(adEvent as AdmobEvent).adShowError(adError)
}
override fun onAdDismissedFullScreenContent() {
super.onAdDismissedFullScreenContent()
showCallBack?.close()
showCallBack = null
adState.onAdHidden()
loadAd(activity.applicationContext, false, AdmobEvent("openAd", "preload"))
}
override fun onAdClicked() {
(adEvent as AdmobEvent).clickAd(this@run.responseInfo)
//计数
LimitUtils.addClickNum()
}
}
show(activity)
}
}
fun loadAd(context: Context, isUnLimit: Boolean, adEvent: AdEvent) {
if (!isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.OPEN, adEvent)) {
this.showCallBack?.close()
this.showCallBack = null
return
}
}
if (!adState.loadingAd) {
adState.loadingAd = true
adEvent.adPulStart()
AppOpenAd.load(
context,
AdConstConfig.ADMOB_OPEN_UNIT_ID,
AdRequest.Builder().build(),
object : AppOpenAd.AppOpenAdLoadCallback() {
override fun onAdLoaded(appOpenAd: AppOpenAd) {
adState.onAdLoaded(appOpenAd)
val ac = adState.activityRef?.get()
if (ac != null) {
show(ac, isUnLimit, adEvent, null)
}
(adEvent as AdmobEvent).pullAd(appOpenAd.responseInfo)
appOpenAd.onPaidEventListener = AdmobEvent.EventOnPaidEventListener(appOpenAd)
LimitUtils.addRequestNum()
}
override fun onAdFailedToLoad(loadAdError: LoadAdError) {
showCallBack?.googleFailed()
showCallBack = null
adState.onAdLoadFailed()
(adEvent as AdmobEvent).pullAd(loadAdError.responseInfo, loadAdError)
}
}
)
}
}
private fun adAvailable() = ((System.currentTimeMillis() - adState.lastLoadTime) / 1000 / 60).toInt() < 30
}
\ No newline at end of file
package com.base.appzxhy.ads.admob
import android.app.Activity
import android.os.Bundle
import com.base.appzxhy.MyApplication
import com.base.appzxhy.ads.AdEvent
import com.base.appzxhy.ads.taichiPref
import com.base.appzxhy.ads.taichiSharedPreferencesEditor
import com.base.appzxhy.helper.EventUtils
import com.base.appzxhy.utils.LogEx
import com.facebook.appevents.AppEventsConstants
import com.facebook.appevents.AppEventsLogger
import com.google.android.gms.ads.AdError
import com.google.android.gms.ads.AdValue
import com.google.android.gms.ads.AdView
import com.google.android.gms.ads.LoadAdError
import com.google.android.gms.ads.OnPaidEventListener
import com.google.android.gms.ads.ResponseInfo
import com.google.android.gms.ads.appopen.AppOpenAd
import com.google.android.gms.ads.interstitial.InterstitialAd
import com.google.android.gms.ads.nativead.NativeAd
import com.google.android.gms.ads.rewarded.RewardedAd
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.ktx.Firebase
import org.json.JSONObject
class AdmobEvent : AdEvent {
override val TAG: String = "AdmobEvent"
constructor(adUnit: String, from: String) : super() {
this.adUnit = adUnit
this.from = from
}
fun pullAd(
responseInfo: ResponseInfo?,
error: LoadAdError? = null,
) {
val obj = JSONObject()
obj.put("req_id", reqId)
if (responseInfo != null) {
val response = responseInfo.adapterResponses.getOrNull(0)
if (response != null) {
obj.put("source", response.adSourceName)
val credentials = mapOf(
"placementid" to response.credentials.get("placementid"),
"appid" to response.credentials.get("appid"),
"pubid" to response.credentials.get("pubid")
)
obj.put("credentials", credentials.toString())
}
obj.put("session_id", responseInfo.responseId)
}
obj.put("networkname", responseInfo?.mediationAdapterClassName)
obj.put("ad_unit", adUnit)
obj.put("from", from)
if (error == null) {
obj.put("status", "1")
} else {
obj.put("errMsg", error.toString())
obj.put("status", "2")
}
EventUtils.event("ad_pull", ext = obj)
LogEx.logDebug(TAG, "ad_pull obj=$obj")
}
fun clickAd(responseInfo: ResponseInfo?) {
val response = responseInfo?.adapterResponses?.getOrNull(0)
val obj = JSONObject()
obj.put("req_id", reqId)
obj.put("source", response?.adSourceName)
obj.put("ad_unit", adUnit)
val credentials = mapOf(
"placementid" to response?.credentials?.get("placementid"),
"appid" to response?.credentials?.get("appid"),
"pubid" to response?.credentials?.get("pubid")
)
obj.put("credentials", credentials.toString())
obj.put("session_id", responseInfo?.responseId)
obj.put("from", from)
obj.put("networkname", responseInfo?.mediationAdapterClassName)
if (adUnit != "nativeAd") {
EventUtils.event("ad_click", ext = obj)
} else {
EventUtils.event("ad_click", ext = obj)
}
}
fun showAd(responseInfo: ResponseInfo?, activity: Activity? = null) {
val response = responseInfo?.adapterResponses?.getOrNull(0)
val obj = JSONObject()
obj.put("req_id", reqId)
obj.put("source", response?.adSourceName)
obj.put("ad_unit", adUnit)
obj.put("networkname", responseInfo?.mediationAdapterClassName)
val credentials = mapOf(
"placementid" to response?.credentials?.get("placementid"),
"appid" to response?.credentials?.get("appid"),
"pubid" to response?.credentials?.get("pubid")
)
obj.put("credentials", credentials.toString())
obj.put("session_id", responseInfo?.responseId)
obj.put("from", activity?.javaClass?.simpleName)
if (adUnit != "nativeAd") {
EventUtils.event("ad_show", ext = obj)
} else {
EventUtils.event("ad_show", ext = obj)
}
LogEx.logDebug(TAG, "ad_show $obj")
}
class EventOnPaidEventListener(private val ad: Any?) : OnPaidEventListener {
override fun onPaidEvent(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)
Firebase.analytics.logEvent("ad_price", Bundle().apply {
putDouble("valueMicros", valueMicros / 1000000.0)
})
val params = Bundle()
val currentImpressionRevenue = adValue.valueMicros.toDouble() / 1000000.0
params.putDouble(FirebaseAnalytics.Param.VALUE, currentImpressionRevenue)
params.putString(FirebaseAnalytics.Param.CURRENCY, "USD")
LogEx.logDebug("EventOnPaidEventListener", "precisionType=${adValue.precisionType}")
val precisionType = when (adValue.precisionType) {
0 -> "UNKNOWN"
1 -> "ESTIMATED"
2 -> "PUBLISHER_PROVIDED"
3 -> "PRECISE"
else -> "Invalid"
}
params.putString("precisionType", precisionType)
Firebase.analytics.logEvent("Ad_Impression_Revenue", params)
val previousTaichiTroasCache = taichiPref.getFloat("TaichiTroasCache", 0f)
val currentTaichiTroasCache = (previousTaichiTroasCache +
currentImpressionRevenue).toFloat()
if (currentTaichiTroasCache >= 0.01) {//如果超过0.01就触发一次tROAS taichi事件
val roasbundle = Bundle()
roasbundle.putDouble(
FirebaseAnalytics.Param.VALUE,
currentTaichiTroasCache.toDouble()
)
roasbundle.putString(FirebaseAnalytics.Param.CURRENCY, "USD")
Firebase.analytics.logEvent("Total_Ads_Revenue_001", roasbundle)
taichiSharedPreferencesEditor.putFloat("TaichiTroasCache", 0f)//重新清零,开始计算
val logger = AppEventsLogger.newLogger(MyApplication.appContext)
val parameters = Bundle()
parameters.putString(AppEventsConstants.EVENT_PARAM_CURRENCY, "USD")
logger.logEvent("ad_value", currentTaichiTroasCache.toDouble(), parameters)
} else {
taichiSharedPreferencesEditor.putFloat("TaichiTroasCache", currentTaichiTroasCache)
}
taichiSharedPreferencesEditor.commit()
var key = "ad_price"
when (ad) {
is AppOpenAd -> {
val adUnitId = ad.adUnitId
val loadedAdapterResponseInfo = ad.responseInfo.loadedAdapterResponseInfo
val adSourceName = loadedAdapterResponseInfo?.adSourceName
val adSourceId = loadedAdapterResponseInfo?.adSourceId
val adSourceInstanceName = loadedAdapterResponseInfo?.adSourceInstanceName
val adSourceInstanceId = loadedAdapterResponseInfo?.adSourceInstanceId
val sessionId = ad.responseInfo.responseId
val extras = ad.responseInfo.responseExtras
val mediationGroupName = extras.getString("mediation_group_name")
val mediationABTestName = extras.getString("mediation_ab_test_name")
val mediationABTestVariant = extras.getString("mediation_ab_test_variant")
obj.put("ad_unit", "openAd")
obj.put("adUnitId", adUnitId)
obj.put("adSourceName", adSourceName)
obj.put("adSourceId", adSourceId)
obj.put("adSourceInstanceName", adSourceInstanceName)
obj.put("adSourceInstanceId", adSourceInstanceId)
obj.put("mediationGroupName", mediationGroupName)
obj.put("mediationABTestName", mediationABTestName)
obj.put("mediationABTestVariant", mediationABTestVariant)
obj.put("session_id", sessionId)
}
is InterstitialAd -> {
val adUnitId = ad.adUnitId
val loadedAdapterResponseInfo = ad.responseInfo.loadedAdapterResponseInfo
val adSourceName = loadedAdapterResponseInfo?.adSourceName
val adSourceId = loadedAdapterResponseInfo?.adSourceId
val adSourceInstanceName = loadedAdapterResponseInfo?.adSourceInstanceName
val adSourceInstanceId = loadedAdapterResponseInfo?.adSourceInstanceId
val sessionId = ad.responseInfo.responseId
val extras = ad.responseInfo.responseExtras
val mediationGroupName = extras.getString("mediation_group_name")
val mediationABTestName = extras.getString("mediation_ab_test_name")
val mediationABTestVariant = extras.getString("mediation_ab_test_variant")
obj.put("ad_unit", "interAd")
obj.put("adUnitId", adUnitId)
obj.put("adSourceName", adSourceName)
obj.put("adSourceId", adSourceId)
obj.put("adSourceInstanceName", adSourceInstanceName)
obj.put("adSourceInstanceId", adSourceInstanceId)
obj.put("mediationGroupName", mediationGroupName)
obj.put("mediationABTestName", mediationABTestName)
obj.put("mediationABTestVariant", mediationABTestVariant)
obj.put("session_id", sessionId)
}
is RewardedAd -> {
val loadedAdapterResponseInfo = ad.responseInfo.loadedAdapterResponseInfo
val adSourceName = loadedAdapterResponseInfo?.adSourceName
val adSourceId = loadedAdapterResponseInfo?.adSourceId
val adSourceInstanceName = loadedAdapterResponseInfo?.adSourceInstanceName
val adSourceInstanceId = loadedAdapterResponseInfo?.adSourceInstanceId
val sessionId = ad.responseInfo.responseId
val extras = ad.responseInfo.responseExtras
val mediationGroupName = extras.getString("mediation_group_name")
val mediationABTestName = extras.getString("mediation_ab_test_name")
val mediationABTestVariant = extras.getString("mediation_ab_test_variant")
obj.put("adSourceName", adSourceName)
obj.put("adSourceId", adSourceId)
obj.put("adSourceInstanceName", adSourceInstanceName)
obj.put("adSourceInstanceId", adSourceInstanceId)
obj.put("mediationGroupName", mediationGroupName)
obj.put("mediationABTestName", mediationABTestName)
obj.put("mediationABTestVariant", mediationABTestVariant)
obj.put("session_id", sessionId)
}
is NativeAd -> {
key = "ad_price"
val loadedAdapterResponseInfo = ad.responseInfo?.loadedAdapterResponseInfo
val adSourceName = loadedAdapterResponseInfo?.adSourceName
val adSourceId = loadedAdapterResponseInfo?.adSourceId
val adSourceInstanceName = loadedAdapterResponseInfo?.adSourceInstanceName
val adSourceInstanceId = loadedAdapterResponseInfo?.adSourceInstanceId
val sessionId = ad.responseInfo?.responseId
val extras = ad.responseInfo?.responseExtras
val mediationGroupName = extras?.getString("mediation_group_name")
val mediationABTestName = extras?.getString("mediation_ab_test_name")
val mediationABTestVariant = extras?.getString("mediation_ab_test_variant")
obj.put("ad_unit", "nativeAd")
obj.put("adSourceName", adSourceName)
obj.put("adSourceId", adSourceId)
obj.put("adSourceInstanceName", adSourceInstanceName)
obj.put("adSourceInstanceId", adSourceInstanceId)
obj.put("mediationGroupName", mediationGroupName)
obj.put("mediationABTestName", mediationABTestName)
obj.put("mediationABTestVariant", mediationABTestVariant)
obj.put("session_id", sessionId)
}
else -> {
runCatching {
val adView = ad as AdView
val adUnitId = adView.adUnitId
val loadedAdapterResponseInfo = adView.responseInfo?.loadedAdapterResponseInfo
val adSourceName = loadedAdapterResponseInfo?.adSourceName
val adSourceId = loadedAdapterResponseInfo?.adSourceId
val adSourceInstanceName = loadedAdapterResponseInfo?.adSourceInstanceName
val adSourceInstanceId = loadedAdapterResponseInfo?.adSourceInstanceId
val sessionId = adView.responseInfo?.responseId
val extras = adView.responseInfo?.responseExtras
val mediationGroupName = extras?.getString("mediation_group_name")
val mediationABTestName = extras?.getString("mediation_ab_test_name")
val mediationABTestVariant = extras?.getString("mediation_ab_test_variant")
obj.put("ad_unit", "banner")
obj.put("adUnitId", adUnitId)
obj.put("adSourceName", adSourceName)
obj.put("adSourceId", adSourceId)
obj.put("adSourceInstanceName", adSourceInstanceName)
obj.put("adSourceInstanceId", adSourceInstanceId)
obj.put("mediationGroupName", mediationGroupName)
obj.put("mediationABTestName", mediationABTestName)
obj.put("mediationABTestVariant", mediationABTestVariant)
obj.put("session_id", sessionId)
}
}
}
EventUtils.event(key, ext = obj)
}
}
fun adShowError(adError: AdError) {
val obj = JSONObject()
obj.put("req_id", reqId)
obj.put("reason", adError.message)
obj.put("code", adError.code)
obj.put("from", from)
obj.put("ad_unit", "openAd")
EventUtils.event("ad_show_error", ext = obj)
LogEx.logDebug(TAG, "ad_show_error $obj")
}
}
package com.base.appzxhy.ads.applovin
import android.os.Bundle
import com.applovin.mediation.MaxAd
import com.applovin.mediation.MaxAdRevenueListener
import com.applovin.mediation.MaxError
import com.applovin.sdk.AppLovinSdk
import com.base.appzxhy.MyApplication
import com.base.appzxhy.ads.AdEvent
import com.base.appzxhy.ads.taichiPref
import com.base.appzxhy.ads.taichiSharedPreferencesEditor
import com.base.appzxhy.helper.EventUtils
import com.base.appzxhy.utils.LogEx
import com.facebook.appevents.AppEventsConstants
import com.facebook.appevents.AppEventsLogger
import com.google.firebase.analytics.FirebaseAnalytics
import org.json.JSONObject
class AdMaxEvent : AdEvent {
override val TAG: String = "AdMaxEvent"
constructor(adUnit: String, from: String) : super() {
this.adUnit = adUnit
this.from = from
}
fun pullAd(
ad: MaxAd?,
error: MaxError? = null
) {
val obj = JSONObject()
obj.put("UnitId", ad?.adUnitId)
obj.put("ad_unit", adUnit)
obj.put(
"creativeId",
ad?.creativeId
)
obj.put("req_id", reqId)
obj.put("from", from)
obj.put("status", if (ad == null) "0" else "1")
obj.put("networkname", ad?.networkName)
obj.put("placement", ad?.placement)
obj.put("networkplacement", ad?.networkPlacement)
obj.put("latency", ad?.requestLatencyMillis)
obj.put("valueMicros", ad?.revenue)
if (error == null) {
obj.put("status", "1")
} else {
obj.put("errMsg", error)
obj.put("status", "2")
}
EventUtils.event("ad_pull", ext = obj)
LogEx.run { logDebug(TAG, "ad_pull $obj") }
}
fun clickAd(ad: MaxAd?) {
val obj = JSONObject()
obj.put("UnitId", ad?.adUnitId)
obj.put("ad_unit", adUnit)
obj.put(
"creativeId",
ad?.creativeId
)
obj.put("networkname", ad?.networkName)
obj.put("placement", ad?.placement)
obj.put("networkplacement", ad?.networkPlacement)
obj.put("latency", ad?.requestLatencyMillis)
obj.put("valueMicros", ad?.revenue)
if (!adUnit.equals("nativeAd")) {
EventUtils.event("ad_click", ext = obj)
} else {
EventUtils.event("ad_click", ext = obj)
}
}
fun showAd(ad: MaxAd?, activity: String?) {
val obj = JSONObject()
obj.put("UnitId", ad?.adUnitId)
obj.put("ad_unit", adUnit)
obj.put(
"creativeId",
ad?.creativeId
)
obj.put("networkname", ad?.networkName)
obj.put("placement", ad?.placement)
obj.put("networkplacement", ad?.networkPlacement)
obj.put("latency", ad?.requestLatencyMillis)
obj.put("valueMicros", ad?.revenue)
obj.put("from", activity)
obj.put("mediation", "applovin")
if (adUnit != "nativeAd") {
EventUtils.event("ad_show", ext = obj)
} else {
EventUtils.event("ad_show", ext = obj)
}
}
class EventOnPaidEventListener : MaxAdRevenueListener {
override fun onAdRevenuePaid(ad: MaxAd) {
val params = Bundle()
val currentImpressionRevenue: Double = ad.revenue // In USD
val mFirebaseAnalytics = FirebaseAnalytics.getInstance(MyApplication.appContext)
params.putString(FirebaseAnalytics.Param.AD_PLATFORM, "appLovin")
params.putString(FirebaseAnalytics.Param.AD_SOURCE, ad.networkName)
params.putString(FirebaseAnalytics.Param.AD_FORMAT, ad.format.getDisplayName())
params.putString(FirebaseAnalytics.Param.AD_UNIT_NAME, ad.adUnitId)
params.putDouble(FirebaseAnalytics.Param.VALUE, currentImpressionRevenue)
params.putString(FirebaseAnalytics.Param.CURRENCY, "USD")
mFirebaseAnalytics.logEvent(FirebaseAnalytics.Event.AD_IMPRESSION, params)
mFirebaseAnalytics.logEvent("Ad_Impression_Revenue", params)
val previousTaichiTroasCache = taichiPref.getFloat("TaichiTroasCache", 0f)
val currentTaichiTroasCache = previousTaichiTroasCache + currentImpressionRevenue
if (currentTaichiTroasCache >= 0.01) {
val roasbundle = Bundle()
roasbundle.putDouble(FirebaseAnalytics.Param.VALUE, currentTaichiTroasCache)
roasbundle.putString(FirebaseAnalytics.Param.CURRENCY, "USD")///(Required)tROAS事件必须
mFirebaseAnalytics.logEvent("Total_Ads_Revenue_001", roasbundle) // 给Taichi用
taichiSharedPreferencesEditor.putFloat("TaichiTroasCache", 0f)//重新清零,开始计算
val logger = AppEventsLogger.newLogger(MyApplication.appContext)
val parameters = Bundle()
parameters.putString(AppEventsConstants.EVENT_PARAM_CURRENCY, "USD")
logger.logEvent("ad_value", currentTaichiTroasCache, parameters)
} else {
taichiSharedPreferencesEditor.putFloat(
"TaichiTroasCache",
currentTaichiTroasCache.toFloat()
)
taichiSharedPreferencesEditor.commit()
}
val obj = JSONObject()
val revenue = ad.revenue
val countryCode =
AppLovinSdk.getInstance(MyApplication.appContext).configuration.countryCode
val networkName = ad.networkName
val adUnitId = ad.adUnitId
val adFormat = ad.format
val placement = ad.placement
val networkPlacement = ad.networkPlacement
obj.put("valueMicros", revenue)
obj.put("currencyCode", countryCode)
obj.put("adUnitId", adUnitId)
obj.put("networkName", networkName)
obj.put("adFormat", adFormat)
obj.put("placement", placement)
obj.put("networkPlacement", networkPlacement)
EventUtils.event("ad_price", ext = obj)
}
}
}
\ No newline at end of file
package com.base.appzxhy.ads.applovin
import android.app.Activity
import android.content.Context
import com.applovin.mediation.MaxAd
import com.applovin.mediation.MaxAdListener
import com.applovin.mediation.MaxError
import com.applovin.mediation.ads.MaxInterstitialAd
import com.base.appzxhy.ads.AdsType
import com.base.appzxhy.ads.AdConstConfig
import com.base.appzxhy.ads.AdDialog.showAdPreparingDialog
import com.base.appzxhy.ads.AdEvent
import com.base.appzxhy.ads.AdsShowCallBack
import com.base.appzxhy.ads.LimitUtils
import com.base.appzxhy.ads.adState
import java.lang.ref.WeakReference
/**
*插屏广告加载显示管理类
*/
class MaxInsertMgr {
private var adState = adState<MaxInterstitialAd>()
private var showCallBack: AdsShowCallBack? = null
fun show(
activity: Activity,
isUnLimit: Boolean,
adEvent: AdEvent,
showCallBack: AdsShowCallBack?
) {
if (activity.isFinishing || activity.isDestroyed) {
showCallBack?.failed(1)
return
}
if (adState.showingAd) {
showCallBack?.failed(2)
return
}
if (showCallBack != null) {
adState.activityRef = WeakReference(activity)
this.showCallBack = showCallBack
if (adState.adDialog == null) {
adState.adDialog = activity.showAdPreparingDialog(2)
}
adEvent.adPrepareShow()
}
if (!adState.loadingAd) {
if (!isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.INSERT, adEvent)) {
showCallBack?.failed(3)
return
}
if (LimitUtils.isIntervalLimited(adState.lastShowTime, adEvent)) {
showCallBack?.failed(4)
return
}
}
if (!adAvailable() || adState.currentAd == null) {
loadAd(activity, isUnLimit, adEvent)
return
}
if (adState.currentAd?.isReady == false) {
loadAd(activity, isUnLimit, adEvent)
return
}
showReadyAd(adEvent)
}
}
private fun showReadyAd(adEvent: AdEvent) {
adState.currentAd?.run {
setListener(object : MaxAdListener {
override fun onAdLoaded(p0: MaxAd) = Unit
override fun onAdLoadFailed(p0: String, p1: MaxError) = Unit
override fun onAdDisplayed(ad: MaxAd) {
adState.onAdDisplayed()
showCallBack?.show()
(adEvent as AdMaxEvent).showAd(ad, activity::class.simpleName)
//计数
LimitUtils.addDisplayNum()
}
override fun onAdDisplayFailed(ad: MaxAd, error: MaxError) {
adState.onAdDisplayFailed()
showCallBack?.googleFailed()
showCallBack = null
(adEvent as AdMaxEvent).adShowError(error)
}
override fun onAdHidden(p0: MaxAd) {
adState.onAdHidden()
showCallBack?.close()
loadAd(activity.applicationContext, false, AdMaxEvent("interAd", "preload"))
}
override fun onAdClicked(ad: MaxAd) {
(adEvent as AdMaxEvent).clickAd(ad)
//计数
LimitUtils.addClickNum()
}
})
setRevenueListener(AdMaxEvent.EventOnPaidEventListener())
showAd(activity)
}
}
fun loadAd(
context: Context,
isUnLimit: Boolean,
adEvent: AdEvent,
) {
if (!isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.INSERT, adEvent)) {
this.showCallBack?.close(4)
this.showCallBack = null
return
}
}
if (!adState.loadingAd) {
adState.loadingAd = true
adEvent.adPulStart()
adState.currentAd = MaxInterstitialAd(AdConstConfig.MAX_INSERT_UNIT_ID, context)
adState.currentAd?.setListener(object : MaxAdListener {
override fun onAdDisplayed(p0: MaxAd) = Unit
override fun onAdHidden(p0: MaxAd) = Unit
override fun onAdClicked(p0: MaxAd) = Unit
override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) = Unit
override fun onAdLoaded(ad: MaxAd) {
adState.onAdLoaded(null)
val ac = adState.activityRef?.get()
if (ac != null) {
show(ac, isUnLimit, adEvent, null)
}
(adEvent as AdMaxEvent).pullAd(ad)
LimitUtils.addRequestNum()
}
override fun onAdLoadFailed(ad: String, error: MaxError) {
adState.onAdLoadFailed()
(adEvent as AdMaxEvent).pullAd(null, error)
showCallBack?.googleFailed(5)
showCallBack = null
}
})
adState.currentAd?.loadAd()
}
}
private fun adAvailable() = ((System.currentTimeMillis() - adState.lastLoadTime) / 1000 / 60).toInt() < 30
}
\ No newline at end of file
package com.base.appzxhy.ads.applovin
import androidx.annotation.LayoutRes
import com.applovin.mediation.MaxAd
import com.applovin.mediation.MaxError
import com.applovin.mediation.nativeAds.MaxNativeAdListener
import com.applovin.mediation.nativeAds.MaxNativeAdLoader
import com.applovin.mediation.nativeAds.MaxNativeAdView
import com.base.appzxhy.ads.AdsType
import com.base.appzxhy.ads.AdConstConfig
import com.base.appzxhy.ads.LimitUtils
import com.base.appzxhy.ads.NativeParentView
import com.base.appzxhy.helper.EventUtils
import org.json.JSONObject
import java.util.UUID
/**
*原生广告加载显示管理类
*/
class MaxNativeMgr {
/**
* 上一次的缓存成功时间
*/
protected var lastTime: Long = 0
/**
* 原生广告
*/
private var currentAd: MaxAd? = null
private var currentLoader: MaxNativeAdLoader? = null
private fun loadAd(
adMaxEvent: AdMaxEvent,
parent: NativeParentView,
@LayoutRes layout: Int
) {
if (!LimitUtils.isAdShow(AdsType.NATIVE, adMaxEvent)) return
val reqId = UUID.randomUUID().toString()
val obj = JSONObject()
obj.put("req_id", reqId)
obj.put("ad_type", "nativeAd")
val nativeAdLoader = MaxNativeAdLoader(AdConstConfig.MAX_NATIVE_UNIT_ID, parent.context)
nativeAdLoader.setNativeAdListener(object : MaxNativeAdListener() {
override fun onNativeAdLoaded(nativeAdView: MaxNativeAdView?, ad: MaxAd) {
currentLoader = nativeAdLoader
currentAd = ad
lastTime = System.currentTimeMillis()
adMaxEvent.pullAd(ad)
nativeAdLoader.setRevenueListener(AdMaxEvent.EventOnPaidEventListener())
show(adMaxEvent, parent, layout)
}
override fun onNativeAdLoadFailed(adUnitId: String, error: MaxError) {
adMaxEvent.pullAd(null, error)
}
override fun onNativeAdClicked(ad: MaxAd) {
}
})
nativeAdLoader.loadAd()
}
fun show(
adMaxEvent: AdMaxEvent,
parent: NativeParentView,
@LayoutRes layout: Int,
nativeCallBack: ((Any?) -> Unit)? = null
) {
if (!LimitUtils.isAdShow(AdsType.NATIVE, adMaxEvent)) {
currentLoader = null
currentAd = null
return
}
val nativeAd = currentAd
val nativeLoader = currentLoader
if ((nativeAd == null || nativeLoader == null).also {
if (it) {
val obj2 = JSONObject()
obj2.put("reason", "no_ad")
obj2.put("ad_unit", "nativeAd")
EventUtils.event("ad_show_error", ext = obj2)
}
} || (!adAvailable()).also {
if (it) {
val obj2 = JSONObject()
obj2.put("ad_unit", "nativeAd")
EventUtils.event("ad_expire", ext = obj2)
}
}) {
//缓存过期了就清空
currentLoader = null
currentAd = null
loadAd(AdMaxEvent("nativeAd", "preload"), parent, layout)
return
}
val obj = JSONObject()
obj.put("ad_unit", "nativeAd")
EventUtils.event("ad_prepare_show", ext = obj)
parent.setNativeAd(nativeLoader!!, nativeAd!!, layout)
nativeCallBack?.invoke(nativeAd)
}
private fun adAvailable(): Boolean {
return ((System.currentTimeMillis() - lastTime) / 1000 / 60).toInt() < 30
}
}
\ No newline at end of file
package com.base.appzxhy.ads.applovin
import android.app.Activity
import android.content.Context
import com.applovin.mediation.MaxAd
import com.applovin.mediation.MaxAdListener
import com.applovin.mediation.MaxError
import com.applovin.mediation.ads.MaxAppOpenAd
import com.base.appzxhy.ads.AdsType
import com.base.appzxhy.ads.AdConstConfig
import com.base.appzxhy.ads.AdEvent
import com.base.appzxhy.ads.AdsShowCallBack
import com.base.appzxhy.ads.LimitUtils
import com.base.appzxhy.ads.adState
import java.lang.ref.WeakReference
/**
* 开屏广告加载显示管理类
*/
class MaxOpenMgr {
private val adState = adState<MaxAppOpenAd>()
private var showCallBack: AdsShowCallBack? = null
fun show(activity: Activity, isUnLimit: Boolean, adEvent: AdEvent, showCallBack: AdsShowCallBack?) {
if (activity.isFinishing || activity.isDestroyed) {
return
}
if (adState.showingAd) {
showCallBack?.failed()
adEvent.adShowError("showingAd")
return
}
if (showCallBack != null) {
this.showCallBack = showCallBack
adState.activityRef = WeakReference(activity)
adEvent.adPrepareShow()
}
if (!adState.loadingAd) {
if (!isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.OPEN, adEvent)) {
showCallBack?.failed()
return
}
if (LimitUtils.isIntervalLimited(adState.lastShowTime, adEvent)) {
showCallBack?.failed()
return
}
}
if (!adAvailable() || adState.currentAd == null) {
loadAd(activity, isUnLimit, adEvent)
return
}
if (adState.currentAd?.isReady != true) {
loadAd(activity, isUnLimit, adEvent)
return
}
showReadyAd(activity, adEvent)
}
}
private fun showReadyAd(activity: Activity, adEvent: AdEvent) {
adState.currentAd?.run {
setListener(object : MaxAdListener {
override fun onAdLoaded(p0: MaxAd) {
}
override fun onAdDisplayed(ad: MaxAd) {
adState.onAdDisplayed()
showCallBack?.show()
LimitUtils.addDisplayNum()
(adEvent as AdMaxEvent).showAd(ad, activity::class.simpleName)
}
override fun onAdHidden(p0: MaxAd) {
adState.onAdHidden()
showCallBack?.close()
showCallBack = null
loadAd(activity.applicationContext, false, AdMaxEvent("openAd", "preload"))
}
override fun onAdClicked(ad: MaxAd) {
(adEvent as AdMaxEvent).clickAd(ad)
//计数
LimitUtils.addClickNum()
}
override fun onAdLoadFailed(p0: String, p1: MaxError) {
}
override fun onAdDisplayFailed(p0: MaxAd, error: MaxError) {
adState.onAdDisplayFailed()
showCallBack?.googleFailed()
showCallBack = null
adEvent.adShowError(error)
}
})
showAd()
}
}
fun loadAd(context: Context, isUnLimit: Boolean, adEvent: AdEvent) {
if (!isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.OPEN, adEvent)) {
this.showCallBack?.close()
this.showCallBack = null
return
}
}
if (!adState.loadingAd) {
adState.loadingAd = true
adEvent.adPulStart()
adState.currentAd = MaxAppOpenAd(AdConstConfig.MAX_OPEN_UNIT_ID, context)
adState.currentAd?.setListener(object : MaxAdListener {
override fun onAdLoaded(ad: MaxAd) {
adState.onAdLoaded(null)
val ac = adState.activityRef?.get()
if (ac != null) {
show(ac, isUnLimit, adEvent, null)
}
(adEvent as AdMaxEvent).pullAd(ad)
LimitUtils.addRequestNum()
}
override fun onAdDisplayed(p0: MaxAd) {
}
override fun onAdHidden(p0: MaxAd) {
}
override fun onAdClicked(p0: MaxAd) {
}
override fun onAdLoadFailed(p0: String, error: MaxError) {
adState.onAdLoadFailed()
showCallBack?.googleFailed()
showCallBack = null
(adEvent as AdMaxEvent).pullAd(null, error)
}
override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) {
}
})
adState.currentAd?.loadAd()
}
}
fun adAvailable() = ((System.currentTimeMillis() - adState.lastLoadTime) / 1000 / 60).toInt() < 30
}
\ No newline at end of file
package com.base.appzxhy.bean.config
class AdConfigBean(
var adSwitch: Boolean = true,//true 走admob,false走max
var numDisplayLimit: Int = -1,
var numRequestLimit: Int = -1,
var numClickLimit: Int = -1,
var timeInterval: Int = 1,
var openAdLoading: Int = 15,
var functionBackShowAd: Boolean = true,
var functionInShowAd: Boolean = true,
)
\ No newline at end of file
package com.base.appzxhy.bean.config
/**
* 后台配置
*/
data class ConfigBean(
var isInBlackList: Boolean = false,
val ut: Int = 0,
val adConfigBean: AdConfigBean = AdConfigBean(),
val popupConfigBean: PopupConfigBean = PopupConfigBean(),
) {
companion object {
var configBean: ConfigBean = ConfigBean()
}
}
\ No newline at end of file
package com.base.appzxhy.bean.config
class PopupConfigBean(
var popupStatus: Boolean = true,
var popupCount: Int = 24,
var popupStart: Int = 0,
var popupEnd: Int = 24,
var popupInterval: Int = 1,
var popupTimerInterval: Int = 1,
var popupFcmInterval: Int = 1,
var popupHoverStatus: Boolean = true,
var popupHoverCount: Int = 5,
var popupHoverDelay: Int = 5000,
//定时器
var timerS: Boolean = true,
var timerDelay: Int = 1,
var timerInterval: Int = 1,
//解锁
var screenS: Boolean = true,
var popupScreenCount: Int = 20,
var popupScreenInterval: Int = 1,
//电量
var batteryS: Boolean = true,
var popupBatteryValue: Int = 20,
var popupBatteryInterval: Int = 1,
//安装卸载
var packageS: Boolean = true,
var popupPackageCount: Int = 20,
var popupPackageInterval: Int = 1
)
\ No newline at end of file
package com.base.appzxhy.ui.main
import com.base.appzxhy.base.BaseFragment
import com.base.appzxhy.databinding.FragmentHomeBinding
class HomeFragment : BaseFragment<FragmentHomeBinding>(FragmentHomeBinding::inflate) {
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#ff8a00" />
<corners android:radius="10dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="180dp"
android:layout_height="136dp"
android:layout_margin="5dp"
app:cardCornerRadius="25dp"
app:cardElevation="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="23dp"
android:src="@mipmap/jiazai_ad"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="18dp"
android:layout_marginBottom="22dp"
android:includeFontPadding="false"
android:text="@string/preparing_advertisement"
android:textColor="@color/black"
android:textSize="13sp"
tools:ignore="HardcodedText" />
</LinearLayout>
</androidx.cardview.widget.CardView>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.HomeFragment">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Home" />
</FrameLayout>
\ No newline at end of file
<com.google.android.gms.ads.nativead.NativeAdView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#f2f2f2"
android:baselineAligned="false">
<com.google.android.gms.ads.nativead.MediaView
android:id="@+id/ad_media"
android:layout_width="91dp"
android:layout_height="91dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="5dp" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="8dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/ad_headline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:textColor="@color/black"
android:textSize="14sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="#FF923E"
android:padding="2dp"
android:text="Ad"
android:textColor="@color/white"
android:textSize="12sp"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/ad_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="10dp"
android:ellipsize="end"
android:maxLines="2"
android:textColor="@color/black"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="5dp">
<ImageView
android:id="@+id/ad_app_icon"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="center_vertical"
tools:ignore="ContentDescription" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/ad_call_to_action"
android:layout_width="match_parent"
android:layout_height="26dp"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="12dp"
android:background="@drawable/bg_ff8a00_10"
android:gravity="center"
android:textColor="@color/white"
android:textSize="15sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</com.google.android.gms.ads.nativead.NativeAdView>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxHeight="300dp"
android:padding="8dp">
<ImageView
android:id="@+id/icon_image_view"
android:layout_width="50dp"
android:layout_height="50dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@mipmap/ic_launcher" />
<TextView
android:id="@+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:background="@android:color/holo_green_dark"
android:padding="2dp"
android:text="Ad"
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
android:textColor="@android:color/white"
app:layout_constraintBottom_toBottomOf="@+id/title_text_view"
app:layout_constraintStart_toEndOf="@+id/icon_image_view"
app:layout_constraintTop_toTopOf="@+id/title_text_view"
tools:ignore="RtlHardcoded,TextContrastCheck" />
<FrameLayout
android:id="@+id/options_view"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_marginBottom="8dp"
android:orientation="horizontal"
app:layout_constraintBottom_toTopOf="@+id/advertiser_text_view"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toEndOf="@+id/title_text_view"
app:layout_constraintTop_toTopOf="@+id/icon_image_view" />
<TextView
android:id="@+id/title_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:textAppearance="@style/TextAppearance.AppCompat.Title"
app:layout_constraintStart_toEndOf="@+id/text_view"
app:layout_constraintTop_toTopOf="parent"
tools:text="Title" />
<TextView
android:id="@+id/advertiser_text_view"
android:layout_width="wrap_content"
android:layout_height="8dp"
android:layout_marginStart="8dp"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
app:layout_constraintBottom_toBottomOf="@+id/icon_image_view"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toEndOf="@+id/icon_image_view"
app:layout_constraintTop_toBottomOf="@+id/title_text_view"
app:layout_constraintVertical_bias="1.0"
tools:text="Advertiser"
tools:textSize="12sp" />
<FrameLayout
android:id="@+id/star_rating_view"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginTop="4dp"
app:layout_constraintBottom_toTopOf="@id/advertiser_text_view"
app:layout_constraintStart_toStartOf="@id/text_view"
app:layout_constraintTop_toBottomOf="@id/text_view" />
<TextView
android:id="@+id/body_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/icon_image_view"
tools:text="Body" />
<FrameLayout
android:id="@+id/media_view_container"
android:layout_width="0dp"
android:layout_height="150dp"
android:layout_marginTop="4dp"
android:maxHeight="150dp"
app:layout_constraintDimensionRatio="W,16:9"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/body_text_view" />
<Button
android:id="@+id/cta_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:backgroundTint="@color/applovin_sdk_brand_color"
android:textColor="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/media_view_container"
tools:layout_editor_absoluteX="8dp"
tools:text="Install" />
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nav_graph">
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_graph"
app:startDestination="@id/homeFragment">
<fragment
android:id="@+id/homeFragment"
android:name="com.base.appzxhy.ui.main.HomeFragment"
android:label="fragment_home"
tools:layout="@layout/fragment_home" />
</navigation>
\ No newline at end of file
<resources>
<string name="app_name">LocalWeatherWhite</string>
<string name="facebook_app_id">1324546913856392</string>
<string name="facebook_app_id">4512448902756291</string>
<string name="home">Home</string>
<string name="turn_on_notification">Turn on notification</string>
<string name="turn_on">Turn on</string>
<string name="preparing_advertisement">Preparing advertisement</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
</resources>
\ No newline at end of file
......@@ -13,6 +13,13 @@ navigationFragmentKtx = "2.6.0"
navigationUiKtx = "2.6.0"
immersionbar = "3.2.2"
playServicesAds = "23.5.0.0"
applovin = "13.0.1"
vungle = "7.4.2.0"
facebook = "6.18.0.0"
mintegral = "16.8.61.0"
pangle = "6.3.0.4.0"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
......@@ -29,6 +36,20 @@ androidx-navigation-fragment-ktx = { group = "androidx.navigation", name = "navi
androidx-navigation-ui-ktx = { group = "androidx.navigation", name = "navigation-ui-ktx", version.ref = "navigationUiKtx" }
vungle = { group = "com.google.ads.mediation", name = "vungle", version.ref = "vungle" }
facebook = { group = "com.google.ads.mediation", name = "facebook", version.ref = "facebook" }
mintegral = { group = "com.google.ads.mediation", name = "mintegral", version.ref = "mintegral" }
pangle = { group = "com.google.ads.mediation", name = "pangle", version.ref = "pangle" }
applovin = { group = "com.applovin", name = "applovin-sdk", version.ref = "applovin" }
applovin_google = { group = "com.applovin.mediation", name = "google-ad-manager-adapter", version.ref = "playServicesAds" }
applovin_admob = { group = "com.applovin.mediation", name = "google-adapter", version.ref = "playServicesAds" }
applovin_vungle = { group = "com.applovin.mediation", name = "vungle-adapter", version.ref = "vungle" }
applovin_facebook = { group = "com.applovin.mediation", name = "facebook-adapter", version.ref = "facebook" }
applovin_mintegral = { group = "com.applovin.mediation", name = "mintegral-adapter", version.ref = "mintegral" }
applovin_pangle = { group = "com.applovin.mediation", name = "bytedance-adapter", version.ref = "pangle" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
......
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