Commit ce276060 authored by wanglei's avatar wanglei

[优化]添加插页场景

parent e2effc51
......@@ -169,19 +169,26 @@ dependencies {
//广告
//admob渠道
implementation(libs.vungle)
implementation(libs.facebook)
implementation(libs.mintegral)
implementation(libs.pangle)
// implementation(libs.vungle)
// implementation(libs.facebook)
// implementation(libs.mintegral)
// implementation(libs.pangle)
//applovin sdk
implementation(libs.applovin)
// 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
// 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
implementation("com.google.android.gms:play-services-ads:23.5.0")
implementation("com.google.ads.mediation:applovin:13.0.1.0")
implementation("com.google.ads.mediation:facebook:6.18.0.0")
implementation("com.google.ads.mediation:mintegral:16.8.61.0")
implementation("com.google.ads.mediation:pangle:6.3.0.4.0")
implementation("com.google.ads.mediation:vungle:7.4.2.0")
val work_version = "2.8.1"
implementation("androidx.work:work-runtime-ktx:$work_version")
......@@ -190,5 +197,7 @@ dependencies {
implementation("com.android.billingclient:billing:$billing_version")
implementation("com.android.billingclient:billing-ktx:$billing_version")
implementation("com.github.JavaNoober.BackgroundLibrary:libraryx:1.7.6")
}
\ No newline at end of file
......@@ -46,6 +46,12 @@
android:exported="false"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".ui.guide.CleanGuideActivity"
android:exported="false"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".ui.guide.GuideActivity"
android:exported="false"
......
......@@ -4,14 +4,16 @@ package com.dumpster.cleaner.bean.config
class AdConfigBean(
var isAdShow: Boolean = true,//广告开关
var adSwitch: Boolean = true,//true 走admob,false走max
var taichiAdValue: Int = 1,//价值上报阀值
var adRatio: Int = 100,//价值上报随机控制
var numDisplayLimit: Int = -1,//展示次数限制
var numRequestLimit: Int = -1,//请求次数限制
var numClickLimit: Int = -1,//点击次数限制
var timeInterval: Int = 10,//广告间隔秒
var timeInterval: Int = 10,//插页广告间隔秒
var timeIntervalOpen: Int = 0,//开屏广告间隔
var openAdLoading: Int = 15,//开屏广告拉取时间
var numNativeDisplayLimit: Int = -1,//原生展示次数限制
......
......@@ -6,9 +6,9 @@ package com.dumpster.cleaner.bean.config
*/
data class ConfigBean(
var isInBlackList: Boolean = false,
// var isInBlackList: Boolean = false,
val ut: Int = 0,
var vpnCanUse: Boolean = true,
// var vpnCanUse: Boolean = true,
val adConfigBean: AdConfigBean = AdConfigBean(),
val popupConfigBean: PopupConfigBean = PopupConfigBean(),
val vipConfigBean: VipConfigBean = VipConfigBean(),
......
......@@ -41,9 +41,9 @@ abstract class AdEvent {
fun adPulStart() {
val obj = JSONObject()
obj.put("req_id", reqId)
obj.put("from", from)
obj.put("ad_unit", adUnit)
obj.put("from", from)
obj.put("req_id", reqId)
obj.put("ad_type", adUnit)
EventUtils.event("ad_pull_start", ext = obj)
LogEx.logDebug(TAG, "ad_pull_start_$adUnit $obj")
......
package com.dumpster.cleaner.business.ads
import android.app.Dialog
import com.dumpster.cleaner.business.ads.LimitUtils.openInterLastShowTime
import com.dumpster.cleaner.business.ads.AdsType.Companion.INSERT
import com.dumpster.cleaner.business.ads.AdsType.Companion.OPEN
import com.dumpster.cleaner.business.ads.LimitUtils.interLastShowTime
import com.dumpster.cleaner.business.ads.LimitUtils.openLastShowTime
class AdState<T>() {
......@@ -34,20 +37,32 @@ class AdState<T>() {
/**
* 广告已经展示
*/
fun onAdDisplayed() {
fun onAdDisplayed(adsType: AdsType) {
currentAd = null
currentAdEvent = null
adDialog?.dismiss()
adDialog = null
openInterLastShowTime = System.currentTimeMillis()
if (adsType == OPEN) {
openLastShowTime = System.currentTimeMillis()
}
if (adsType == INSERT) {
interLastShowTime = System.currentTimeMillis()
}
}
fun onAdHidden() {
fun onAdHidden(adsType: AdsType) {
//重置下上次展示的时间,避免看广告的时间算入间隔
openInterLastShowTime = System.currentTimeMillis()
if (adsType == OPEN) {
openLastShowTime = System.currentTimeMillis()
}
if (adsType == INSERT) {
interLastShowTime = System.currentTimeMillis()
}
}
......@@ -59,14 +74,14 @@ class AdState<T>() {
currentAdEvent = null
}
fun onAdLoaded(ad: T?, adEvent: AdEvent?) {
//这里可能提前设置,所有可以不设置,max回调的类型可能不同
if (ad != null) {
currentAd = ad
}
if (adEvent != null) {
currentAdEvent = adEvent
}
fun loadStart(adEvent: AdEvent) {
loadingAd = true
currentAdEvent = adEvent
}
fun onAdLoaded(ad: T?) {
currentAd = ad
loadingAd = false
lastLoadTime = System.currentTimeMillis()
}
......@@ -81,4 +96,5 @@ class AdState<T>() {
fun adAvailable() =
currentAd != null || ((System.currentTimeMillis() - lastLoadTime) / 1000 / 60).toInt() < 30
}
......@@ -18,10 +18,10 @@ import com.dumpster.cleaner.business.ads.admob.AdInterMgr
import com.dumpster.cleaner.business.ads.admob.AdNativeMgr
import com.dumpster.cleaner.business.ads.admob.AdOpenMgr
import com.dumpster.cleaner.business.ads.admob.AdmobEvent
import com.dumpster.cleaner.business.ads.applovin.AdMaxEvent
import com.dumpster.cleaner.business.ads.applovin.MaxInsertMgr
import com.dumpster.cleaner.business.ads.applovin.MaxNativeMgr
import com.dumpster.cleaner.business.ads.applovin.MaxOpenMgr
//import com.dumpster.cleaner.business.ads.applovin.AdMaxEvent
//import com.dumpster.cleaner.business.ads.applovin.MaxInsertMgr
//import com.dumpster.cleaner.business.ads.applovin.MaxNativeMgr
//import com.dumpster.cleaner.business.ads.applovin.MaxOpenMgr
import com.dumpster.cleaner.business.helper.EventUtils
import com.dumpster.cleaner.utils.AppPreferences
import com.dumpster.cleaner.utils.LogEx
......@@ -49,15 +49,15 @@ object AdsMgr {
private val adBannerMgr by lazy {
AdBannerMgr()
}
private val maxOpenMgr by lazy {
MaxOpenMgr()
}
private val maxInsertMgr by lazy {
MaxInsertMgr()
}
private val maxNativeMgr by lazy {
MaxNativeMgr()
}
// private val maxOpenMgr by lazy {
// MaxOpenMgr()
// }
// private val maxInsertMgr by lazy {
// MaxInsertMgr()
// }
// private val maxNativeMgr by lazy {
// MaxNativeMgr()
// }
/**
* 是否初始化
......@@ -87,12 +87,12 @@ object AdsMgr {
*/
fun init(context: Context) {
if (configBean.isInBlackList) {
EventUtils.event("isInBlackList", value = "isInBlackList=${configBean.isInBlackList}")
return
}
// if (configBean.isInBlackList) {
// EventUtils.event("isInBlackList", value = "isInBlackList=${configBean.isInBlackList}")
// return
// }
initAdmob(context)
initMax(context)
// initMax(context)
}
......@@ -106,7 +106,7 @@ object AdsMgr {
EventUtils.event("AdmobInit", "AdmobInit=$isAdmobInit")
// context.toast("admob init")
if (adsConfigBean.adSwitch) {
if (true) {
admobInitCallBack?.invoke()
admobInitCallBack = null
adNativeMgr.loadAd(context, AdmobEvent("nativeAd", context::class.java.simpleName))
......@@ -117,38 +117,38 @@ object AdsMgr {
}
private fun initMax(context: Context) = kotlin.runCatching {
if (isMaxInit) return@runCatching
val executor = Executors.newSingleThreadExecutor()
executor.execute {
val currentGaid = AdvertisingIdClient.getAdvertisingIdInfo(context).id
AppPreferences.getInstance().getString("gid", currentGaid)
val build = AppLovinSdkInitializationConfiguration
.builder(GlobalConfig.KEY_MAX, context)
build.mediationProvider = 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, AdMaxEvent("interAd", context::class.java.simpleName))
context.toast("max init")
maxInitCallBack?.invoke()
maxInitCallBack = null
}
}
}
}
}
// private fun initMax(context: Context) = kotlin.runCatching {
// if (isMaxInit) return@runCatching
// val executor = Executors.newSingleThreadExecutor()
//
// executor.execute {
// val currentGaid = AdvertisingIdClient.getAdvertisingIdInfo(context).id
// AppPreferences.getInstance().getString("gid", currentGaid)
//
// val build = AppLovinSdkInitializationConfiguration
// .builder(GlobalConfig.KEY_MAX, context)
//
// build.mediationProvider = 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, AdMaxEvent("interAd", context::class.java.simpleName))
// context.toast("max init")
// maxInitCallBack?.invoke()
// maxInitCallBack = null
// }
// }
// }
//
// }
//
// }
var admobInitCallBack: (() -> Unit)? = null
var maxInitCallBack: (() -> Unit)? = null
......@@ -172,14 +172,14 @@ object AdsMgr {
return
}
if (configBean.isInBlackList) {
EventUtils.event("isInBlackList", "isInBlackList=${configBean.isInBlackList}")
showCallBack?.failed()
return
}
// if (configBean.isInBlackList) {
// EventUtils.event("isInBlackList", "isInBlackList=${configBean.isInBlackList}")
// showCallBack?.failed()
// return
// }
val from = activity::class.java.simpleName
if (adsConfigBean.adSwitch) {
if (true) {
val admobEvent = AdmobEvent("openAd", from).apply { this.isUnLimit = isUnLimit }
if (isAdmobInit) {
adOpenMgr.show(activity, admobEvent, showCallBack)
......@@ -189,13 +189,13 @@ object AdsMgr {
adOpenMgr.show(activity, admobEvent, showCallBack)
}
} else {
if (isMaxInit) {
maxOpenMgr.show(activity, isUnLimit, AdMaxEvent("openAd", from), showCallBack)
} else {
maxInitCallBack = {
maxOpenMgr.show(activity, isUnLimit, AdMaxEvent("openAd", from), showCallBack)
}
}
// if (isMaxInit) {
// maxOpenMgr.show(activity, isUnLimit, AdMaxEvent("openAd", from), showCallBack)
// } else {
// maxInitCallBack = {
// maxOpenMgr.show(activity, isUnLimit, AdMaxEvent("openAd", from), showCallBack)
// }
// }
}
}
......@@ -219,17 +219,16 @@ object AdsMgr {
return
}
if (configBean.isInBlackList) {
EventUtils.event("isInBlackList", configBean.isInBlackList.toString())
showCallBack?.failed()
return
}
LogEx.logDebug("showAd", "adSwitch=${adsConfigBean.adSwitch}")
// if (configBean.isInBlackList) {
// EventUtils.event("isInBlackList", configBean.isInBlackList.toString())
// showCallBack?.failed()
// return
// }
val from = activity::class.java.simpleName
if (adsConfigBean.adSwitch) {
if (true) {
adInterMgr.show(activity, AdmobEvent("interAd", from).apply { this.isUnLimit = isUnLimit }, showCallBack)
} else {
maxInsertMgr.show(activity, isUnLimit, AdMaxEvent("interAd", from), showCallBack)
// maxInsertMgr.show(activity, isUnLimit, AdMaxEvent("interAd", from), showCallBack)
}
}
......@@ -250,16 +249,16 @@ object AdsMgr {
return
}
nativeView.visibility = View.VISIBLE
if (configBean.isInBlackList) {
EventUtils.event("isInBlackList", configBean.isInBlackList.toString())
return
}
// if (configBean.isInBlackList) {
// EventUtils.event("isInBlackList", configBean.isInBlackList.toString())
// return
// }
val showNative = {
if (adsConfigBean.adSwitch) {
if (true) {
adNativeMgr.show(AdmobEvent("nativeAd", "nativeAd"), nativeView, layout, nativeCallBack)
} else {
maxNativeMgr.show(AdMaxEvent("nativeAd", "nativeAd"), nativeView, layout, nativeCallBack)
// maxNativeMgr.show(AdMaxEvent("nativeAd", "nativeAd"), nativeView, layout, nativeCallBack)
}
}
......@@ -282,11 +281,11 @@ object AdsMgr {
return
}
parent.visibility = View.VISIBLE
if (configBean.isInBlackList) {
EventUtils.event("isInBlackList", configBean.isInBlackList.toString())
return
}
if (adsConfigBean.adSwitch) {
// if (configBean.isInBlackList) {
// EventUtils.event("isInBlackList", configBean.isInBlackList.toString())
// return
// }
if (true) {
adBannerMgr.show(parent, collapsible, adClose)
}
}
......
......@@ -151,26 +151,48 @@ object LimitUtils {
/**
* 开屏和插页广告的显示间隔限制
* 开屏限制
*/
fun isIntervalLimited(adEvent: AdEvent): Boolean {
val flag = ((System.currentTimeMillis() - openInterLastShowTime) / 1000).toInt() < (AdConfigBean.adsConfigBean.timeInterval)
fun isIntervalOpenLimit(adEvent: AdEvent): Boolean {
val flag = ((System.currentTimeMillis() - openLastShowTime) / 1000).toInt() < (AdConfigBean.adsConfigBean.timeIntervalOpen)
if (flag) {
adEvent.adShowError("ad in timeInterval")
}
return flag
}
//开屏和插页上一次展示时间共用,避免开屏插页连弹
var openInterLastShowTime = 0L
/**
* 插屏限制
*/
fun isIntervalInterLimit(adEvent: AdEvent): Boolean {
val flag = ((System.currentTimeMillis() - interLastShowTime) / 1000).toInt() < (AdConfigBean.adsConfigBean.timeInterval)
if (flag) {
adEvent.adShowError("ad in timeInterval")
}
return flag
}
//开屏上次展示时间
var openLastShowTime = 0L
get() {
return AppPreferences.getInstance().getLong("openInterLastShowTime", field)
return AppPreferences.getInstance().getLong("openLastShowTime", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("openInterLastShowTime", value, true)
AppPreferences.getInstance().put("openLastShowTime", value, true)
}
//插屏上次展示时间
var interLastShowTime = 0L
get() {
return AppPreferences.getInstance().getLong("interLastShowTime", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("interLastShowTime", value, true)
}
/**
* 原生广告是否到达限制
*/
......
......@@ -4,7 +4,6 @@ import android.os.Bundle
import android.view.ViewGroup
import android.view.ViewTreeObserver
import com.dumpster.cleaner.GlobalConfig
import com.dumpster.cleaner.bean.config.AdConfigBean
import com.dumpster.cleaner.business.ads.AdsType
import com.dumpster.cleaner.business.ads.LimitUtils
import com.dumpster.cleaner.business.ads.admob.AdmobEvent.AdmobOnPaidEventListener
......@@ -26,9 +25,9 @@ class AdBannerMgr {
fun show(parent: ViewGroup, collapsible: Boolean, adClose: (() -> Unit)? = null) {
if (!AdConfigBean.adsConfigBean.adSwitch) {
return
}
// if (!AdConfigBean.adsConfigBean.adSwitch) {
// return
// }
val admobEvent = AdmobEvent("banner", "banner")
if (!LimitUtils.isAdShow(AdsType.BANNER, admobEvent)) {
......
......@@ -11,6 +11,7 @@ import com.dumpster.cleaner.business.ads.AdEvent
import com.dumpster.cleaner.business.ads.AdState
import com.dumpster.cleaner.business.ads.AdsShowCallBack
import com.dumpster.cleaner.business.ads.AdsType
import com.dumpster.cleaner.business.ads.AdsType.Companion.OPEN
import com.dumpster.cleaner.business.ads.LimitUtils
import com.dumpster.cleaner.business.ads.admob.AdmobEvent.AdmobOnPaidEventListener
import com.dumpster.cleaner.utils.LogEx
......@@ -32,7 +33,7 @@ class AdInterMgr {
//正在加载回调
private var loadingCallBack: (() -> Unit)? = null
private var loadingCallBack: ((flag: Boolean) -> Unit)? = null
fun show(
activity: Activity,
......@@ -44,16 +45,15 @@ class AdInterMgr {
return
}
val nowAdEvent = adEvent
//currentAdEvent!=null 表示有缓存广告,关联reqId
adState.currentAdEvent?.let { nowAdEvent.reqId = it.reqId }
adState.currentAdEvent?.let { adEvent.reqId = it.reqId }
if (!nowAdEvent.isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.INSERT, nowAdEvent)) {
if (!adEvent.isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.INSERT, adEvent)) {
showCallBack?.failed(2)
return
}
if (LimitUtils.isIntervalLimited(nowAdEvent)) {
if (LimitUtils.isIntervalInterLimit(adEvent)) {
showCallBack?.failed(3)
return
}
......@@ -69,24 +69,29 @@ class AdInterMgr {
adState.adDialog?.dismiss()
}
nowAdEvent.adPrepareShow()
adEvent.adPrepareShow()
LogEx.logDebug(adEvent.TAG, "needLoad=$needLoad")
if (needLoad) {
if (!adState.loadingAd) {
LogEx.logDebug(adEvent.TAG, "inter adState !loadingAd")
loadAd(activity, nowAdEvent) {
showReadyAd(activity, nowAdEvent)
loadAd(activity, adEvent) {
if (it) {
showReadyAd(activity, adEvent)
} else {
showCallBack?.adFailed()
}
}
} else {
LogEx.logDebug(adEvent.TAG, "inter adState is loadingAd")
loadingCallBack = {
showReadyAd(activity, nowAdEvent)
showReadyAd(activity, adEvent)
}
}
} else {
LogEx.logDebug(adEvent.TAG, "inter ad ready")
showReadyAd(activity, nowAdEvent)
showReadyAd(activity, adEvent)
}
}
......@@ -113,7 +118,7 @@ class AdInterMgr {
admobEvent.showAd(responseInfo, ac)
adState.onAdDisplayed()
adState.onAdDisplayed(OPEN)
showCallBack?.show()
LimitUtils.addDisplayNum()
......@@ -132,7 +137,7 @@ class AdInterMgr {
override fun onAdDismissedFullScreenContent() {
super.onAdDismissedFullScreenContent()
adState.onAdHidden()
adState.onAdHidden(OPEN)
showCallBack?.close()
showCallBack = null
......@@ -160,7 +165,7 @@ class AdInterMgr {
fun loadAd(
context: Context,
adEvent: AdEvent,
loadCallBack: (() -> Unit)? = null
loadCallBack: ((flag: Boolean) -> Unit)? = null
) {
if (!adEvent.isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.INSERT, adEvent)) {
......@@ -172,14 +177,12 @@ class AdInterMgr {
}
//避免无效预加载
if (adState.loadingAd && loadCallBack == null && loadingCallBack == null) {
//容错机制
adState.loadingAd = false
if (adState.loadingAd) {
return
}
adState.loadingAd = true
adEvent.adPulStart()
adState.loadStart(adEvent)
InterstitialAd.load(
context, GlobalConfig.ID_ADMOB_INTER, AdRequest.Builder().build(),
......@@ -187,10 +190,10 @@ class AdInterMgr {
override fun onAdLoaded(ad: InterstitialAd) {
val event = (adEvent as AdmobEvent)
ad.onPaidEventListener = AdmobOnPaidEventListener(ad, adEvent.scope)
adState.onAdLoaded(ad, adEvent)
adState.onAdLoaded(ad)
loadCallBack?.invoke()
loadingCallBack?.invoke()
loadCallBack?.invoke(true)
loadingCallBack?.invoke(true)
loadingCallBack = null
LimitUtils.addRequestNum()
......@@ -199,11 +202,14 @@ class AdInterMgr {
override fun onAdFailedToLoad(loadAdError: LoadAdError) {
adState.onAdLoadFailed()
if (loadCallBack != null) {
adState.onAdDisplayFailed()
}
showCallBack?.adFailed()
showCallBack = null
loadCallBack?.invoke(false)
loadingCallBack?.invoke(false)
loadingCallBack = null
(adEvent as AdmobEvent).pullAd(loadAdError.responseInfo, loadAdError)
}
......
......@@ -8,6 +8,7 @@ import com.dumpster.cleaner.business.ads.AdEvent
import com.dumpster.cleaner.business.ads.AdState
import com.dumpster.cleaner.business.ads.AdsShowCallBack
import com.dumpster.cleaner.business.ads.AdsType
import com.dumpster.cleaner.business.ads.AdsType.Companion.INSERT
import com.dumpster.cleaner.business.ads.LimitUtils
import com.dumpster.cleaner.business.ads.admob.AdmobEvent.AdmobOnPaidEventListener
import com.dumpster.cleaner.utils.LogEx
......@@ -27,7 +28,7 @@ class AdOpenMgr {
private var showCallBack: AdsShowCallBack? = null
//正在加载回调
private var loadingCallBack: (() -> Unit)? = null
private var loadingCallBack: ((flag: Boolean) -> Unit)? = null
fun show(
activity: Activity,
......@@ -38,15 +39,14 @@ class AdOpenMgr {
return
}
val nowAdEvent = adEvent
adState.currentAdEvent?.let { nowAdEvent.reqId = it.reqId }
adState.currentAdEvent?.let { adEvent.reqId = it.reqId }
if (!nowAdEvent.isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.OPEN, nowAdEvent)) {
if (!adEvent.isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.OPEN, adEvent)) {
showCallBack?.failed()
return
}
if (LimitUtils.isIntervalLimited(nowAdEvent)) {
if (LimitUtils.isIntervalOpenLimit(adEvent)) {
showCallBack?.failed()
return
}
......@@ -55,26 +55,36 @@ class AdOpenMgr {
val needLoad = !adState.adAvailable()
this.showCallBack = showCallBack
nowAdEvent.adPrepareShow()
adEvent.adPrepareShow()
if (needLoad) {
if (!adState.loadingAd) {
LogEx.logDebug(adEvent.TAG, "open adState !loadingAd")
loadAd(activity, adEvent) {
showReadyAd(activity)
if (it) {
showReadyAd(activity, adEvent)
} else {
showCallBack?.adFailed()
}
}
} else {
LogEx.logDebug(adEvent.TAG, "open adState is loadingAd")
loadingCallBack = {
showReadyAd(activity)
if (it) {
showReadyAd(activity, adEvent)
} else {
showCallBack?.adFailed()
}
}
}
} else {
LogEx.logDebug(adEvent.TAG, "open ad ready")
showReadyAd(activity)
showReadyAd(activity, adEvent)
}
}
private fun showReadyAd(ac: Activity) {
private fun showReadyAd(ac: Activity, adEvent: AdEvent) {
val admobEvent = (adEvent as AdmobEvent)
if (ac.isFinishing || ac.isDestroyed || adState.currentAd == null) {
LogEx.logDebug(TAG, "showReadyAd ac=null isFinishing isDestroyed")
......@@ -83,16 +93,15 @@ class AdOpenMgr {
adState.currentAd?.run {
val adEvent = adState.currentAdEvent as AdmobEvent?
fullScreenContentCallback = object : FullScreenContentCallback() {
override fun onAdShowedFullScreenContent() {
adEvent?.showAd(this@run.responseInfo, ac)
admobEvent.showAd(this@run.responseInfo, ac)
showCallBack?.show()
adState.onAdDisplayed()
adState.onAdDisplayed(INSERT)
//计数
LimitUtils.addDisplayNum()
......@@ -105,7 +114,7 @@ class AdOpenMgr {
showCallBack = null
adState.onAdDisplayFailed()
adEvent?.adShowError(adError)
admobEvent.adShowError(adError)
}
......@@ -115,15 +124,14 @@ class AdOpenMgr {
showCallBack?.close()
showCallBack = null
adState.onAdHidden()
adState.onAdHidden(INSERT)
//预加载,“Timeout for show call succeed.”预加载的广告大概率,
loadAd(MyApplication.appContext, AdmobEvent("openAd", "preload"))
}
override fun onAdClicked() {
adEvent?.clickAd(this@run.responseInfo)
admobEvent.clickAd(this@run.responseInfo)
//计数
LimitUtils.addClickNum()
}
......@@ -135,7 +143,7 @@ class AdOpenMgr {
fun loadAd(
context: Context,
adEvent: AdEvent,
loadCallBack: (() -> Unit)? = null
loadCallBack: ((flag: Boolean) -> Unit)? = null
) {
if (!adEvent.isUnLimit) {
......@@ -148,14 +156,12 @@ class AdOpenMgr {
}
//避免无效预加载
if (adState.loadingAd && loadCallBack == null && loadingCallBack == null) {
//容错机制
adState.loadingAd = false
if (adState.loadingAd) {
return
}
adState.loadingAd = true
adEvent.adPulStart()
adState.loadStart(adEvent)
AppOpenAd.load(
context,
......@@ -163,21 +169,27 @@ class AdOpenMgr {
AdRequest.Builder().build(),
object : AppOpenAd.AppOpenAdLoadCallback() {
override fun onAdLoaded(appOpenAd: AppOpenAd) {
adState.onAdLoaded(appOpenAd, adEvent)
LogEx.logDebug(adEvent.TAG, "open onAdLoaded loadAd")
loadCallBack?.invoke()
loadingCallBack?.invoke()
appOpenAd.onPaidEventListener = AdmobOnPaidEventListener(appOpenAd, adEvent.scope)
adState.onAdLoaded(appOpenAd)
loadCallBack?.invoke(true)
loadingCallBack?.invoke(true)
loadingCallBack = null
(adEvent as AdmobEvent).pullAd(appOpenAd.responseInfo)
appOpenAd.onPaidEventListener = AdmobOnPaidEventListener(appOpenAd, adEvent.scope)
LimitUtils.addRequestNum()
(adEvent as AdmobEvent).pullAd(appOpenAd.responseInfo)
}
override fun onAdFailedToLoad(loadAdError: LoadAdError) {
showCallBack?.adFailed()
showCallBack = null
LogEx.logDebug(adEvent.TAG, "open onAdFailedToLoad loadAd")
adState.onAdLoadFailed()
loadCallBack?.invoke(false)
loadingCallBack?.invoke(false)
loadingCallBack = null
(adEvent as AdmobEvent).pullAd(loadAdError.responseInfo, loadAdError)
}
}
......
......@@ -49,6 +49,8 @@ class AdmobEvent : AdEvent {
) {
var key = "ad_pull"
val obj = JSONObject()
obj.put("ad_unit", adUnit)
obj.put("from", from)
obj.put("req_id", reqId)
if (responseInfo != null) {
val response = responseInfo.adapterResponses.getOrNull(0)
......@@ -65,8 +67,6 @@ class AdmobEvent : AdEvent {
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 {
......@@ -75,7 +75,7 @@ class AdmobEvent : AdEvent {
key = "ad_pull_error"
}
EventUtils.event(key, ext = obj)
LogEx.logDebug(TAG, "ad_pull obj=$obj")
LogEx.logDebug(TAG, "${key}_$adUnit obj=$obj")
}
......
package com.dumpster.cleaner.business.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.dumpster.cleaner.GlobalConfig
import com.dumpster.cleaner.business.ads.AdsType
import com.dumpster.cleaner.business.ads.LimitUtils
import com.dumpster.cleaner.business.ads.NativeParentView
import com.dumpster.cleaner.business.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(GlobalConfig.ID_MAX_NATIVE, 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.dumpster.cleaner.business.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.dumpster.cleaner.GlobalConfig
//import com.dumpster.cleaner.business.ads.AdsType
//import com.dumpster.cleaner.business.ads.LimitUtils
//import com.dumpster.cleaner.business.ads.NativeParentView
//import com.dumpster.cleaner.business.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(GlobalConfig.ID_MAX_NATIVE, 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
......@@ -17,6 +17,7 @@ import com.dumpster.cleaner.base.cleanFileBeans
import com.dumpster.cleaner.bean.FeatureBean.Companion.JUNK_CLEAN
import com.dumpster.cleaner.bean.FileBean
import com.dumpster.cleaner.business.ads.AdsMgr
import com.dumpster.cleaner.business.ads.AdsShowCallBack
import com.dumpster.cleaner.databinding.ActivityJunkCleanBinding
import com.dumpster.cleaner.databinding.ItemJunkCleanChildBinding
import com.dumpster.cleaner.databinding.ItemJunkCleanGroupBinding
......@@ -133,6 +134,11 @@ class JunkCleanActivity : BaseActivity<ActivityJunkCleanBinding>(ActivityJunkCle
selectedFiles = list.flatMap { it.items.takeIf { it.isNotEmpty() }?.filter { it.isSelected } ?: emptyList() }
total = selectedFiles.sumOf { it.length }
setClean()
AdsMgr.showInsert(this, true, showCallBack = object : AdsShowCallBack() {
override fun next() {
binding.idShouzhi.visibility = View.VISIBLE
}
})
}
......
package com.dumpster.cleaner.ui.guide
import android.animation.Animator
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import com.dumpster.cleaner.R
import com.dumpster.cleaner.base.BaseActivity
import com.dumpster.cleaner.base.jumpAction
import com.dumpster.cleaner.bean.FeatureBean.Companion.JUNK_CLEAN
import com.dumpster.cleaner.business.ads.AdsMgr
import com.dumpster.cleaner.business.ads.AdsShowCallBack
import com.dumpster.cleaner.databinding.ActivityLayoutCleanGuideBinding
import com.dumpster.cleaner.ui.dialog.StoragePermissionDialog
import com.dumpster.cleaner.ui.dialog.permissionStorageJump
import com.dumpster.cleaner.ui.main.MainActivity
import com.dumpster.cleaner.utils.BarUtils
import com.dumpster.cleaner.utils.PermissionUtils.checkStorePermission
import com.dumpster.cleaner.utils.PermissionUtils.requestStoragePermission
class CleanGuideActivity : BaseActivity<ActivityLayoutCleanGuideBinding>(ActivityLayoutCleanGuideBinding::inflate) {
override fun useDefaultImmersive() {
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, 0, systemBars.right, systemBars.bottom)
insets
}
}
override fun initView() {
super.initView()
binding.root.updatePadding(top = BarUtils.getStatusBarHeight())
play1()
}
override fun initListener() {
binding.idSkip.setOnClickListener {
AdsMgr.showInsert(this, true, object : AdsShowCallBack() {
override fun next() {
goToAc(MainActivity::class.java)
finish()
}
})
}
binding.idClean02.setOnClickListener {
val jump = {
jumpAction(JUNK_CLEAN)
finish()
}
if (this.checkStorePermission()) {
jump.invoke()
} else {
val dialog = StoragePermissionDialog(this)
dialog.action = {
requestStoragePermission(launcher) {
if (it) {
jump.invoke()
}
}
}
dialog.showDialog()
}
}
}
private fun play1() {
binding.idLottieview.setAnimation(R.raw.firstscan)
binding.idLottieview.playAnimation()
binding.idLottieview.addAnimatorListener(createAnimatorListener())
binding.idLottieview.addAnimatorUpdateListener { animation ->
// 获取动画的当前进度(0.0f 到 1.0f)
val progress = animation.animatedFraction
// 将进度条的进度设置为动画进度的百分比
binding.idProg01.progress = (progress * 100).toInt()
if (binding.idProg01.progress == 50) {
play2()
}
}
binding.idProg01.progress = 0
binding.idProg01.max = 50
}
private fun play2() {
binding.idLottieview.setAnimation(R.raw.firstscan_finish)
binding.idLottieview.playAnimation()
binding.idLl01.isVisible = false
binding.idLl02.isVisible = true
binding.idSkip.isVisible = true
}
private fun createAnimatorListener(): Animator.AnimatorListener {
return object : Animator.AnimatorListener {
override fun onAnimationStart(p0: Animator) {
// 动画开始时调用
}
override fun onAnimationEnd(p0: Animator) {
// 动画结束时调用
}
override fun onAnimationCancel(p0: Animator) {
// 动画被取消时调用
}
override fun onAnimationRepeat(p0: Animator) {
// 动画重复时调用
}
}
}
override fun handleBackCallBack() {
binding.idSkip.callOnClick()
}
}
\ No newline at end of file
......@@ -35,7 +35,7 @@ import com.dumpster.cleaner.business.helper.NewComUtils.spConfig
import com.dumpster.cleaner.business.service.StayJobService.Companion.startStayJobService
import com.dumpster.cleaner.databinding.ActivitySplashBinding
import com.dumpster.cleaner.ui.dialog.StoragePermissionDialog
import com.dumpster.cleaner.ui.guide.GuideCleanActivity
import com.dumpster.cleaner.ui.guide.CleanGuideActivity
import com.dumpster.cleaner.ui.main.MainActivity
import com.dumpster.cleaner.utils.LogEx
import com.dumpster.cleaner.utils.PermissionUtils.checkStorePermission
......@@ -84,6 +84,9 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>(ActivitySplashBinding
requestNotificationPermission()
showLoadingAd()
setPrivacyPolicy()
viewModel.jumpNext={
actionIdJump()
}
}
private fun setPrivacyPolicy() {
......@@ -235,7 +238,7 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>(ActivitySplashBinding
when {
!isGuided -> {
isGuided = true
goToAc(GuideCleanActivity::class.java)
goToAc(CleanGuideActivity::class.java)
finish()
}
......
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="5dp" />
<solid android:color="@color/white" />
</shape>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="5dp" />
<solid android:color="#6AFAE7" />
</shape>
</clip>
</item>
</layer-list>
\ 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary">
<com.noober.background.view.BLTextView
android:id="@+id/id_skip"
android:layout_width="92dp"
android:layout_height="36dp"
android:layout_marginTop="36dp"
android:layout_marginEnd="20dp"
android:gravity="center"
android:text="Skip"
android:textColor="@color/colorPrimary"
android:textSize="16sp"
android:visibility="gone"
app:bl_corners_radius="50dp"
app:bl_solid_color="#B0FFFFFF"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/id_lottieview"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/id_fl_bottom"
app:layout_constraintTop_toTopOf="parent" />
<FrameLayout
android:id="@+id/id_fl_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="100dp"
app:layout_constraintBottom_toBottomOf="parent">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/id_ll01"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
android:visibility="visible">
<ProgressBar
android:id="@+id/id_prog_01"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="16dp"
android:layout_marginHorizontal="28dp"
android:progressDrawable="@drawable/guide_pro" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="12dp"
android:text="Scanning the phone..."
android:textColor="@color/white"
android:textSize="15sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="22dp"
android:layout_marginTop="4dp"
android:gravity="center"
android:text="To find unnecessary files completely, the first scan may take a moment."
android:textColor="#91E2FF"
android:textSize="13sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/id_ll02"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
android:visibility="gone">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="12dp"
android:text="Click the button to clean the phone"
android:textColor="@color/white"
android:textSize="15sp"
android:textStyle="bold" />
<com.noober.background.view.BLTextView
android:id="@+id/id_clean_02"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginHorizontal="50dp"
android:layout_marginTop="18dp"
android:gravity="center"
android:text="Clean"
android:textColor="@color/colorPrimary"
android:textSize="19sp"
android:textStyle="bold"
app:bl_corners_radius="90dp"
app:bl_solid_color="#6AFAE7" />
</androidx.appcompat.widget.LinearLayoutCompat>
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
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