Commit 9fb1d6e9 authored by wanglei's avatar wanglei

...

parent d0327d41
......@@ -99,11 +99,20 @@ dependencies {
//广告
implementation("com.google.android.gms:play-services-ads:23.1.0")
implementation("com.google.ads.mediation:applovin:12.4.3.0")
implementation("com.google.ads.mediation:facebook:6.17.0.0")
implementation("com.google.ads.mediation:mintegral:16.7.21.0")
implementation("com.google.ads.mediation:pangle:5.9.0.4.0")
//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
//firebase
implementation(platform("com.google.firebase:firebase-bom:32.3.1"))
......
package com.base.locationsharewhite.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.locationsharewhite.databinding.DialogAdPreparingBinding
import com.base.locationsharewhite.utils.DensityUtils
object AdDialog {
fun Context.showAdPreparingDialog(): AlertDialog {
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
......@@ -69,8 +69,8 @@ object AdsMgr {
* @param activity 当前页面
* @param showCallBack 展示回调
*/
fun showOpen(activity: Activity, showCallBack: AdsShowCallBack? = null) {
adOpenMgr.show(activity, showCallBack)
fun showOpen(activity: Activity, isUnLimit: Boolean = false, showCallBack: AdsShowCallBack? = null) {
adOpenMgr.show(activity, isUnLimit, showCallBack)
}
/**
......@@ -79,12 +79,16 @@ object AdsMgr {
* @param activity 当前页面
* @param showCallBack 展示回调
*/
fun showInsert(activity: Activity, showCallBack: AdsShowCallBack? = null) {
fun showInsert(
activity: Activity,
isUnLimit: Boolean = false,
showCallBack: AdsShowCallBack? = null
) {
if (!isInit || adsConfigBean?.isInBlackList != false) {
showCallBack?.failed()
return
}
adInsertMgr.show(activity, showCallBack)
adInsertMgr.show(activity, isUnLimit, showCallBack)
}
/**
......
......@@ -46,14 +46,14 @@ abstract class BaseAdMgr<T> {
*
* @param context 加载所用的上下文,一般使用appContext
*/
abstract fun loadAd(context: Context)
abstract fun loadAd(context: Context, isUnLimit: Boolean = true)
/**
* 广告显示
*
* @param activity 当前页面
*/
abstract fun show(activity: Activity, showCallBack: AdsShowCallBack? = null)
abstract fun show(activity: Activity, isUnLimit: Boolean = true, showCallBack: AdsShowCallBack? = null)
/**
......
package com.base.locationsharewhite.ads
import com.base.locationsharewhite.BuildConfig
/**
* 部分常量配置相关,如admob广告位id与通知渠道等
*/
object ConstConfig {
//用于替换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
//云控remoteConfig对应的key
const val REMOTE_MSG = "MsgConfig"//云控消息配置对应的key
const val REMOTE_AD = "AdmobConfig"//云控广告配置对应的key
//admob test id
const val OPEN_ADMOB_ID_TEST = "ca-app-pub-3940256099942544/9257395921"
const val BANNER_ADMOB_ID_TEST = "ca-app-pub-3940256099942544/9214589741"
const val INTER_ADMOB_ID_TEST = "ca-app-pub-3940256099942544/1033173712"
const val NATIVE_ADMOB_ID_TEST = "ca-app-pub-3940256099942544/2247696110"
// admob广告id
const val INTER_ADMOB_ID = "ca-app-pub-7560983767776658/7069786941"
const val NATIVE_ADMOB_ID = "ca-app-pub-7560983767776658/5561264154"
const val OPEN_ADMOB_ID = "ca-app-pub-7560983767776658/9504378590"
const val BANNER_ADMOB_ID = "ca-app-pub-7560983767776658/7704383208"
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.locationsharewhite.ads
import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
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.locationsharewhite.R
import com.google.android.gms.ads.nativead.NativeAd
import com.google.android.gms.ads.nativead.NativeAdView
@SuppressLint("ViewConstructor")
class CustomParentNativeView(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)
}
}
\ No newline at end of file
......@@ -4,7 +4,7 @@ import android.os.Bundle
import android.view.ViewGroup
import android.view.ViewTreeObserver
import com.base.locationsharewhite.ads.AdsType
import com.base.locationsharewhite.helper.config.ConstConfig
import com.base.locationsharewhite.ads.ConstConfig
import com.google.ads.mediation.admob.AdMobAdapter
import com.google.android.gms.ads.AdListener
import com.google.android.gms.ads.AdRequest
......@@ -41,7 +41,7 @@ class AdBannerMgr {
val adWidth = (parent.width / screenPixelDensity).toInt()
val adSize =
AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(parent.context, adWidth)
adView?.adUnitId = ConstConfig.bannerAdId
adView?.adUnitId = ConstConfig.ADMOB_BANNER_UNIT_ID
adView?.setAdSize(adSize)
loadAd(adClose)
parent.viewTreeObserver.removeOnGlobalLayoutListener(listener)
......
......@@ -2,11 +2,12 @@ package com.base.locationsharewhite.ads.admob
import android.app.Activity
import android.content.Context
import com.base.locationsharewhite.ads.AdDialog.showAdPreparingDialog
import com.base.locationsharewhite.ads.AdsShowCallBack
import com.base.locationsharewhite.ads.AdsType
import com.base.locationsharewhite.ads.BaseAdMgr
import com.base.locationsharewhite.ads.ConstConfig.ADMOB_INSERT_UNIT_ID
import com.base.locationsharewhite.helper.EventUtils
import com.base.locationsharewhite.helper.config.ConstConfig
import com.google.android.gms.ads.AdError
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.FullScreenContentCallback
......@@ -24,8 +25,8 @@ class AdInsertMgr : BaseAdMgr<InterstitialAd>() {
private var lastOpenDate: Long = 0
override fun loadAd(context: Context) {
if (!loadingAd && LimitUtils.isAdShow(AdsType.INSERT)) {
override fun loadAd(context: Context, isUnLimit: Boolean) {
if ((!loadingAd && LimitUtils.isAdShow(AdsType.INSERT)) || isUnLimit) {
loadingAd = true
//计数
LimitUtils.addRequestNum()
......@@ -36,8 +37,7 @@ class AdInsertMgr : BaseAdMgr<InterstitialAd>() {
obj.put("from", context.javaClass.simpleName)
EventUtils.event("ad_pull_start", ext = obj)
InterstitialAd.load(
context,
ConstConfig.insertAdId,
context, ADMOB_INSERT_UNIT_ID,
AdRequest.Builder().build(),
object : InterstitialAdLoadCallback() {
override fun onAdLoaded(ad: InterstitialAd) {
......@@ -50,7 +50,7 @@ class AdInsertMgr : BaseAdMgr<InterstitialAd>() {
lastTime = System.currentTimeMillis()
val ac = activityRef?.get()
if (ac != null) {
show(ac)
show(ac, isUnLimit = isUnLimit)
}
}
......@@ -76,18 +76,20 @@ class AdInsertMgr : BaseAdMgr<InterstitialAd>() {
}
}
override fun show(activity: Activity, showCallBack: AdsShowCallBack?) {
override fun show(activity: Activity, isUnLimit: Boolean, showCallBack: AdsShowCallBack?) {
if (activity.isFinishing || activity.isDestroyed) {
showCallBack?.failed()
return
}
if (!LimitUtils.isAdShow(AdsType.INSERT)) {
showCallBack?.failed()
return
}
if (LimitUtils.isIntervalLimited(lastOpenDate)) {
showCallBack?.failed()
return
if (!isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.INSERT)) {
showCallBack?.failed()
return
}
if (LimitUtils.isIntervalLimited(lastOpenDate)) {
showCallBack?.failed()
return
}
}
if (showingAd) {
// 开屏广告正在展示
......@@ -126,6 +128,7 @@ class AdInsertMgr : BaseAdMgr<InterstitialAd>() {
}
return
}
val dialog = activity.showAdPreparingDialog()
val obj1 = JSONObject()
obj1.put("ad_unit", "interAd")
EventUtils.event("ad_prepare_show", ext = obj1)
......@@ -133,6 +136,7 @@ class AdInsertMgr : BaseAdMgr<InterstitialAd>() {
fullScreenContentCallback = object : FullScreenContentCallback() {
override fun onAdShowedFullScreenContent() {
super.onAdShowedFullScreenContent()
dialog.cancel()
lastOpenDate = System.currentTimeMillis()
// 广告展示
currentAd = null
......@@ -145,6 +149,7 @@ class AdInsertMgr : BaseAdMgr<InterstitialAd>() {
override fun onAdFailedToShowFullScreenContent(adError: AdError) {
super.onAdFailedToShowFullScreenContent(adError)
dialog.cancel()
// 广告展示失败,清空缓存数据,重新加载
showingAd = false
currentAd = null
......
......@@ -4,8 +4,8 @@ import android.content.Context
import android.view.ViewGroup
import androidx.core.view.isVisible
import com.base.locationsharewhite.ads.AdsType
import com.base.locationsharewhite.ads.ConstConfig
import com.base.locationsharewhite.helper.EventUtils
import com.base.locationsharewhite.helper.config.ConstConfig
import com.base.locationsharewhite.utils.LogEx
import com.google.android.gms.ads.AdListener
import com.google.android.gms.ads.AdLoader
......@@ -41,38 +41,31 @@ class AdNativeMgr {
obj.put("ad_type", "nativeAd")
val adLoader = AdLoader.Builder(
context,
ConstConfig.nativeAdId
)
.forNativeAd { nativeAd ->
cacheItems.offer(nativeAd)
lastTime = System.currentTimeMillis()
nativeAd.setOnPaidEventListener(AdmobEvent.EventOnPaidEventListener(nativeAd))
AdmobEvent.pullAd(nativeAd.responseInfo, "nativeAd", reqId = reqId)
if (parent != null && layout != null) show(parent, layout)
ConstConfig.ADMOB_NATIVE_UNIT_ID
).forNativeAd { nativeAd ->
cacheItems.offer(nativeAd)
lastTime = System.currentTimeMillis()
nativeAd.setOnPaidEventListener(AdmobEvent.EventOnPaidEventListener(nativeAd))
AdmobEvent.pullAd(nativeAd.responseInfo, "nativeAd", reqId = reqId)
if (parent != null && layout != null) show(parent, layout)
}.withAdListener(object : AdListener() {
override fun onAdFailedToLoad(error: LoadAdError) {
AdmobEvent.pullAd(error.responseInfo, "nativeAd", error.message, reqId = reqId)
}
.withAdListener(object : AdListener() {
override fun onAdFailedToLoad(error: LoadAdError) {
AdmobEvent.pullAd(error.responseInfo, "nativeAd", error.message, reqId = reqId)
}
override fun onAdClicked() {
super.onAdClicked()
AdmobEvent.clickAd(cacheItems.lastOrNull()?.responseInfo, "nativeAd")
}
override fun onAdClicked() {
super.onAdClicked()
AdmobEvent.clickAd(cacheItems.lastOrNull()?.responseInfo, "nativeAd")
}
override fun onAdClosed() {
super.onAdClosed()
}
})
.withNativeAdOptions(
NativeAdOptions.Builder()
// .setAdChoicesPlacement(NativeAdOptions.ADCHOICES_TOP_RIGHT)
// .setMediaAspectRatio(NativeAdOptions.NATIVE_MEDIA_ASPECT_RATIO_SQUARE)
.build()
)
.build()
// Load AdMob native advanced ads
override fun onAdClosed() {
super.onAdClosed()
}
}).withNativeAdOptions(
NativeAdOptions.Builder()
.build()
).build()
adLoader.loadAds(AdRequest.Builder().build(), 1)
}
......
......@@ -5,8 +5,8 @@ import android.content.Context
import com.base.locationsharewhite.ads.AdsShowCallBack
import com.base.locationsharewhite.ads.AdsType
import com.base.locationsharewhite.ads.BaseAdMgr
import com.base.locationsharewhite.ads.ConstConfig
import com.base.locationsharewhite.helper.EventUtils
import com.base.locationsharewhite.helper.config.ConstConfig
import com.google.android.gms.ads.AdError
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.FullScreenContentCallback
......@@ -23,7 +23,7 @@ class AdOpenMgr : BaseAdMgr<AppOpenAd>() {
private var lastOpenDate: Long = 0
override fun loadAd(context: Context) {
override fun loadAd(context: Context, isUnLimit: Boolean) {
if (!loadingAd && LimitUtils.isAdShow(AdsType.OPEN)) {
loadingAd = true
//计数
......@@ -35,7 +35,7 @@ class AdOpenMgr : BaseAdMgr<AppOpenAd>() {
EventUtils.event("ad_pull_start", ext = obj)
AppOpenAd.load(
context,
ConstConfig.openAdId,
ConstConfig.ADMOB_OPEN_UNIT_ID,
AdRequest.Builder().build(),
object : AppOpenAd.AppOpenAdLoadCallback() {
override fun onAdLoaded(appOpenAd: AppOpenAd) {
......@@ -75,7 +75,7 @@ class AdOpenMgr : BaseAdMgr<AppOpenAd>() {
}
}
override fun show(activity: Activity, showCallBack: AdsShowCallBack?) {
override fun show(activity: Activity, isUnLimit: Boolean, showCallBack: AdsShowCallBack?) {
if (activity.isFinishing || activity.isDestroyed) {
showCallBack?.failed()
return
......
package com.base.locationsharewhite.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.locationsharewhite.ads.AdsShowCallBack
import com.base.locationsharewhite.ads.AdsType
import com.base.locationsharewhite.ads.BaseAdMgr
import com.base.locationsharewhite.ads.ConstConfig
import com.base.locationsharewhite.ads.admob.LimitUtils
import com.base.locationsharewhite.helper.EventUtils
import org.json.JSONObject
import java.lang.ref.WeakReference
import java.util.UUID
/**
*插屏广告加载显示管理类
*/
class MaxInsertMgr : BaseAdMgr<MaxInterstitialAd>() {
private var lastOpenDate: Long = 0
override fun loadAd(context: Context, isUnLimit: Boolean) {
if ((!loadingAd && LimitUtils.isAdShow(AdsType.INSERT)) || isUnLimit) {
loadingAd = true
//计数
LimitUtils.addRequestNum()
val reqId = UUID.randomUUID().toString()
val obj = JSONObject()
obj.put("req_id", reqId)
obj.put("ad_type", "interAd")
obj.put("from", context.javaClass.simpleName)
EventUtils.event("ad_pull_start", ext = obj)
currentAd = MaxInterstitialAd(ConstConfig.MAX_INSERT_UNIT_ID, context)
currentAd?.setListener(object : MaxAdListener {
override fun onAdLoaded(p0: MaxAd) {
// AdmobEvent.pullAd(ad.responseInfo, "interAd", reqId = reqId)
// ad.onPaidEventListener = AdmobEvent.EventOnPaidEventListener(ad)
// 开屏广告加载成功
loadingAd = false
lastTime = System.currentTimeMillis()
val ac = activityRef?.get()
if (ac != null) {
show(ac, isUnLimit = isUnLimit)
}
}
override fun onAdDisplayed(p0: MaxAd) {
}
override fun onAdHidden(p0: MaxAd) {
}
override fun onAdClicked(p0: MaxAd) {
}
override fun onAdLoadFailed(p0: String, p1: MaxError) {
// AdmobEvent.pullAd(
// loadAdError.responseInfo,
// "interAd",
// loadAdError.message,
// reqId = reqId
// )
// 广告加载失败
// 官方不建议在此回调中重新加载广告
loadingAd = false
if (activityRef != null && !showingAd && showCallBack != null) {
showCallBack?.googleFailed()
showCallBack = null
}
}
override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) {
}
})
currentAd?.loadAd()
}
}
override fun show(activity: Activity, isUnLimit: Boolean, showCallBack: AdsShowCallBack?) {
if (activity.isFinishing || activity.isDestroyed) {
showCallBack?.failed()
return
}
if (!LimitUtils.isAdShow(AdsType.INSERT)) {
showCallBack?.failed()
return
}
if (LimitUtils.isIntervalLimited(lastOpenDate)) {
showCallBack?.failed()
return
}
if (showingAd) {
// 开屏广告正在展示
return
}
if (showCallBack != null && this.showCallBack != showCallBack) this.showCallBack =
showCallBack
if ((currentAd?.isReady != true).also {
if (it) {
val obj = JSONObject()
obj.put("reason", "no_ad")
obj.put("ad_unit", "interAd")
EventUtils.event("ad_show_error", ext = obj)
}
} || (!adAvailable()).also {
if (it) {
val obj2 = JSONObject()
obj2.put("ad_unit", "interAd")
EventUtils.event("ad_expire", ext = obj2)
}
}) {
//缓存广告过期
currentAd = null
if (activityRef == null) {
activityRef = WeakReference(activity)
// 开屏广告不可用或者缓存超时过期,重新加载
loadAd(activity.applicationContext, isUnLimit)
} else {
activityRef = null
this.showCallBack?.failed()
this.showCallBack = null
val obj = JSONObject()
obj.put("reason", "no_ad")
obj.put("ad_unit", "interAd")
EventUtils.event("ad_show_error", ext = obj)
}
return
}
val obj1 = JSONObject()
obj1.put("ad_unit", "interAd")
EventUtils.event("ad_prepare_show", ext = obj1)
currentAd?.run {
setListener(object : MaxAdListener {
override fun onAdLoaded(p0: MaxAd) {
}
override fun onAdDisplayed(p0: MaxAd) {
lastOpenDate = System.currentTimeMillis()
// 广告展示
currentAd = null
activityRef = null
this@MaxInsertMgr.showCallBack?.show()
// AdmobEvent.showAd(this@run.responseInfo, "interAd", activity)
//计数
LimitUtils.addDisplayNum()
}
override fun onAdHidden(p0: MaxAd) {
// 广告关闭,清空缓存数据,重新加载
showingAd = false
this@MaxInsertMgr.showCallBack?.close()
this@MaxInsertMgr.showCallBack = null
loadAd(activity.applicationContext)
}
override fun onAdClicked(p0: MaxAd) {
// AdmobEvent.clickAd(this@run.responseInfo, "interAd")
//计数
LimitUtils.addClickNum()
}
override fun onAdLoadFailed(p0: String, p1: MaxError) {
}
override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) {
// 广告展示失败,清空缓存数据,重新加载
showingAd = false
currentAd = null
activityRef = null
this@MaxInsertMgr.showCallBack?.googleFailed()
this@MaxInsertMgr.showCallBack = null
val obj = JSONObject()
obj.put("reason", p1.message)
obj.put("code", p1.code)
obj.put("ad_unit", "interAd")
EventUtils.event("ad_show_error", ext = obj)
}
})
showingAd = true
showAd(activity)
}
}
override fun adAvailable() = ((System.currentTimeMillis() - lastTime) / 1000 / 60).toInt() < 30
}
\ No newline at end of file
package com.base.locationsharewhite.ads.applovin
import android.content.Context
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.locationsharewhite.ads.AdsType
import com.base.locationsharewhite.ads.ConstConfig
import com.base.locationsharewhite.ads.CustomParentNativeView
import com.base.locationsharewhite.ads.admob.LimitUtils
import com.base.locationsharewhite.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
fun loadAd(context: Context, parent: CustomParentNativeView? = null, @LayoutRes layout: Int? = null) {
if (!LimitUtils.isAdShow(AdsType.NATIVE)) return
val reqId = UUID.randomUUID().toString()
val obj = JSONObject()
obj.put("req_id", reqId)
obj.put("ad_type", "nativeAd")
val nativeAdLoader = MaxNativeAdLoader(ConstConfig.MAX_NATIVE_UNIT_ID, context)
nativeAdLoader.setNativeAdListener(object : MaxNativeAdListener() {
override fun onNativeAdLoaded(nativeAdView: MaxNativeAdView?, ad: MaxAd) {
currentLoader = nativeAdLoader
currentAd = ad
lastTime = System.currentTimeMillis()
// nativeAd.setOnPaidEventListener(AdmobEvent.EventOnPaidEventListener(nativeAd))
// AdmobEvent.pullAd(nativeAd.responseInfo, "nativeAd", reqId = reqId)
if (parent != null && layout != null) show(parent, layout)
}
override fun onNativeAdLoadFailed(adUnitId: String, error: MaxError) {
}
override fun onNativeAdClicked(ad: MaxAd) {
}
})
nativeAdLoader.loadAd()
}
fun show(parent: CustomParentNativeView, @LayoutRes layout: Int? = null) {
if (!LimitUtils.isAdShow(AdsType.NATIVE)) {
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(parent.context.applicationContext, parent, layout)
return
}
val obj = JSONObject()
obj.put("ad_unit", "nativeAd")
EventUtils.event("ad_prepare_show_native", ext = obj)
parent.setNativeAd(nativeLoader!!, nativeAd!!, layout)
// loadAd(parent.context.applicationContext)
}
fun adAvailable(): Boolean {
return ((System.currentTimeMillis() - lastTime) / 1000 / 60).toInt() < 30
}
}
\ No newline at end of file
package com.base.locationsharewhite.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.locationsharewhite.ads.AdsShowCallBack
import com.base.locationsharewhite.ads.AdsType
import com.base.locationsharewhite.ads.BaseAdMgr
import com.base.locationsharewhite.ads.ConstConfig
import com.base.locationsharewhite.ads.admob.LimitUtils
import com.base.locationsharewhite.helper.EventUtils
import org.json.JSONObject
import java.lang.ref.WeakReference
import java.util.UUID
/**
* 开屏广告加载显示管理类
*/
class MaxOpenMgr : BaseAdMgr<MaxAppOpenAd>() {
private var lastOpenDate: Long = 0
override fun loadAd(context: Context, isUnLimit: Boolean) {
if (!(loadingAd && LimitUtils.isAdShow(AdsType.OPEN)) || isUnLimit) {
loadingAd = true
//计数
LimitUtils.addRequestNum()
val reqId = UUID.randomUUID().toString()
val obj = JSONObject()
obj.put("req_id", reqId)
obj.put("ad_type", "openAd")
EventUtils.event("ad_pull_start", ext = obj)
currentAd = MaxAppOpenAd(ConstConfig.MAX_OPEN_UNIT_ID, context)
currentAd?.setListener(object : MaxAdListener {
override fun onAdLoaded(p0: MaxAd) {
loadingAd = false
lastTime = System.currentTimeMillis()
val ac = activityRef?.get()
if (ac != null) {
show(ac, isUnLimit = isUnLimit)
}
// AdmobEvent.pullAd(appOpenAd.responseInfo, "openAd", reqId = reqId)
// appOpenAd.onPaidEventListener =
// AdmobEvent.EventOnPaidEventListener(appOpenAd)
}
override fun onAdDisplayed(p0: MaxAd) {
}
override fun onAdHidden(p0: MaxAd) {
}
override fun onAdClicked(p0: MaxAd) {
}
override fun onAdLoadFailed(p0: String, p1: MaxError) {
loadingAd = false
if (activityRef != null && !showingAd && showCallBack != null) {
showCallBack?.googleFailed()
showCallBack = null
}
// AdmobEvent.pullAd(
// loadAdError.responseInfo,
// "openAd",
// loadAdError.message,
// reqId = reqId
// )
}
override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) {
}
})
currentAd?.loadAd()
}
}
override fun show(activity: Activity, isUnLimit: Boolean, showCallBack: AdsShowCallBack?) {
if (activity.isFinishing || activity.isDestroyed) {
showCallBack?.failed()
return
}
if (!isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.OPEN)) {
showCallBack?.failed()
return
}
if (LimitUtils.isIntervalLimited(lastOpenDate)) {
showCallBack?.failed()
return
}
}
if (showingAd) {
// 开屏广告正在展示
return
}
if (showCallBack != null && this.showCallBack != showCallBack) this.showCallBack =
showCallBack
if ((currentAd?.isReady != true).also {
if (it) {
val obj = JSONObject()
obj.put("reason", "no_ad")
obj.put("ad_unit", "openAd")
EventUtils.event("ad_show_error", ext = obj)
}
} || (!adAvailable()).also {
if (it) {
val obj2 = JSONObject()
obj2.put("ad_unit", "openAd")
EventUtils.event("ad_expire", ext = obj2)
}
}) {
//缓存广告过期
currentAd = null
if (activityRef == null) {
activityRef = WeakReference(activity)
// 开屏广告不可用或者缓存超时过期,重新加载
loadAd(activity.applicationContext, isUnLimit)
} else {
activityRef = null
this.showCallBack?.failed()
this.showCallBack = null
val obj = JSONObject()
obj.put("reason", "no_ad")
obj.put("ad_unit", "openAd")
EventUtils.event("ad_show_error", ext = obj)
}
return
}
val obj1 = JSONObject()
obj1.put("ad_unit", "openAd")
EventUtils.event("ad_prepare_show", ext = obj1)
currentAd?.run {
setListener(object : MaxAdListener {
override fun onAdLoaded(p0: MaxAd) {
}
override fun onAdDisplayed(p0: MaxAd) {
lastOpenDate = System.currentTimeMillis()
// 广告展示
currentAd = null
activityRef = null
this@MaxOpenMgr.showCallBack?.show()
//计数
LimitUtils.addDisplayNum()
// AdmobEvent.showAd(this@run.responseInfo, "openAd", activity)
}
override fun onAdHidden(p0: MaxAd) {
// 广告关闭,清空缓存数据,重新加载
showingAd = false
this@MaxOpenMgr.showCallBack?.close()
this@MaxOpenMgr.showCallBack = null
loadAd(activity.applicationContext)
}
override fun onAdClicked(p0: MaxAd) {
// AdmobEvent.clickAd(this@run.responseInfo, "openAd")
//计数
LimitUtils.addClickNum()
}
override fun onAdLoadFailed(p0: String, p1: MaxError) {
}
override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) {
// 广告展示失败,清空缓存数据,重新加载
showingAd = false
currentAd = null
activityRef = null
this@MaxOpenMgr.showCallBack?.googleFailed()
this@MaxOpenMgr.showCallBack = null
val obj = JSONObject()
obj.put("reason", p1.message)
obj.put("code", p1.code)
obj.put("ad_unit", "openAd")
EventUtils.event("ad_show_error", ext = obj)
}
})
showingAd = true
showAd()
}
}
override fun adAvailable() = ((System.currentTimeMillis() - lastTime) / 1000 / 60).toInt() < 30
}
\ No newline at end of file
package com.base.locationsharewhite.helper.config
import com.base.locationsharewhite.BuildConfig
import com.base.locationsharewhite.R
/**
* 部分常量配置相关,如admob广告位id与通知渠道等
*/
object ConstConfig {
//用于替换广告位,区分debug与正式广告位id
inline val openAdId get() = if (BuildConfig.DEBUG) openAdmobIdTest else openAdmobId
inline val bannerAdId get() = if (BuildConfig.DEBUG) bannerAdmobIdTest else bannerAdmobId
inline val insertAdId get() = if (BuildConfig.DEBUG) interAdmobIdTest else interAdmobId
inline val nativeAdId get() = if (BuildConfig.DEBUG) nativeAdmobIdTest else nativeAdmobId
//admob test id
const val openAdmobIdTest = "ca-app-pub-3940256099942544/9257395921"
const val bannerAdmobIdTest = "ca-app-pub-3940256099942544/9214589741"
const val interAdmobIdTest = "ca-app-pub-3940256099942544/1033173712"
const val nativeAdmobIdTest = "ca-app-pub-3940256099942544/2247696110"
// admob广告id
const val interAdmobId = "ca-app-pub-3940256099942544/1033173111"
const val nativeAdmobId = "ca-app-pub-3940256099942544/2247696111"
const val openAdmobId = "/6499/example/app-open"
const val bannerAdmobId = "ca-app-pub-3940256099942544/9214581111"
}
\ No newline at end of file
package com.base.locationsharewhite.utils;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import com.base.locationsharewhite.helper.MyApplication;
/**
* 做尺寸转换的工具类。在dp/sp/px之间自由转换
*
* @noinspection unused
*/
public class DensityUtils {
@SuppressLint("StaticFieldLeak")
static Context context = MyApplication.appContext;
public static int dip2px(float dipValue) {
float scale = context.getResources()
.getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
public static int dip2px(float dipValue, float toScale) {
float scale = context.getResources()
.getDisplayMetrics().density;
return (int) ((dipValue * scale + 0.5f) * toScale);
}
public static int px2dip(float pxValue) {
float scale = context.getResources()
.getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
public static int px2sp(float pxValue) {
float scale = context.getResources()
.getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
public static int sp2px(float spValue) {
float scale = context.getResources()
.getDisplayMetrics().density;
return (int) (spValue * scale + 0.5f);
}
public static int getWidth() {
initScreen();
if (screen != null) {
return screen.widthPixels;
}
return 0;
}
public static int getHeight() {
initScreen();
if (screen != null) {
return screen.heightPixels;
}
return 0;
}
/**
* @noinspection SuspiciousNameCombination
*/
static void initScreen() {
if (screen == null) {
DisplayMetrics dm = new DisplayMetrics();
WindowManager windowManager = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getMetrics(dm);
if (dm.widthPixels > dm.heightPixels) {
screen = new Screen(dm.heightPixels, dm.widthPixels);
} else {
screen = new Screen(dm.widthPixels, dm.heightPixels);
}
}
}
static Screen screen = null;
public static class Screen {
public int widthPixels;
public int heightPixels;
public Screen() {
}
public Screen(int widthPixels, int heightPixels) {
this.widthPixels = widthPixels;
this.heightPixels = heightPixels;
}
@NonNull
@Override
public String toString() {
return "(" + widthPixels + "," + heightPixels + ")";
}
}
/**
* Get Screen Real Width 包含状态栏导航栏
*
* @return Real Width
*/
public static int getRealWidth() {
Display display = getDisplay(context);
if (display == null) {
return 0;
}
DisplayMetrics dm = new DisplayMetrics();
display.getRealMetrics(dm);
return dm.widthPixels;
}
/**
* Get Screen Real Height 包含状态栏导航栏
*
* @return Real Height
*/
public static int getRealHeight() {
Display display = getDisplay(context);
if (display == null) {
return 0;
}
DisplayMetrics dm = new DisplayMetrics();
display.getRealMetrics(dm);
return dm.heightPixels;
}
/**
* Get Display
*
* @param context Context for get WindowManager
* @return Display
*/
private static Display getDisplay(Context context) {
WindowManager wm;
if (context instanceof Activity) {
Activity activity = (Activity) context;
wm = activity.getWindowManager();
} else {
wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
}
if (wm != null) {
return wm.getDefaultDisplay();
}
return null;
}
/**
* Get Screen Height 不含状态栏导航栏
*/
public static int getScreenHeight(Context context) {
return context.getResources().getDisplayMetrics().heightPixels;
}
/**
* Get Screen Width 不含状态栏导航栏
*/
public static int getScreenWidth(Context context) {
return context.getResources().getDisplayMetrics().widthPixels;
}
}
<?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>
......@@ -12,6 +12,13 @@ constraintlayout = "2.1.4"
playServicesMaps = "18.1.0"
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" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
......@@ -24,6 +31,20 @@ androidx-constraintlayout = { group = "androidx.constraintlayout", name = "const
play-services-maps = { group = "com.google.android.gms", name = "play-services-maps", version.ref = "playServicesMaps" }
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]
androidApplication = { id = "com.android.application", version.ref = "agp" }
jetbrainsKotlinAndroid = { 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