Commit ce276060 authored by wanglei's avatar wanglei

[优化]添加插页场景

parent e2effc51
...@@ -169,19 +169,26 @@ dependencies { ...@@ -169,19 +169,26 @@ dependencies {
//广告 //广告
//admob渠道 //admob渠道
implementation(libs.vungle) // implementation(libs.vungle)
implementation(libs.facebook) // implementation(libs.facebook)
implementation(libs.mintegral) // implementation(libs.mintegral)
implementation(libs.pangle) // implementation(libs.pangle)
//applovin sdk //applovin sdk
implementation(libs.applovin) // implementation(libs.applovin)
//applovin渠道 //applovin渠道
implementation(libs.applovin.google) // implementation(libs.applovin.google)
implementation(libs.applovin.admob) // implementation(libs.applovin.admob)
implementation(libs.applovin.facebook) //meta // implementation(libs.applovin.facebook) //meta
implementation(libs.applovin.mintegral)//mintegral // implementation(libs.applovin.mintegral)//mintegral
implementation(libs.applovin.pangle) //pangle // implementation(libs.applovin.pangle) //pangle
implementation(libs.applovin.vungle) //vungle // 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" val work_version = "2.8.1"
implementation("androidx.work:work-runtime-ktx:$work_version") implementation("androidx.work:work-runtime-ktx:$work_version")
...@@ -190,5 +197,7 @@ dependencies { ...@@ -190,5 +197,7 @@ dependencies {
implementation("com.android.billingclient:billing:$billing_version") implementation("com.android.billingclient:billing:$billing_version")
implementation("com.android.billingclient:billing-ktx:$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 @@ ...@@ -46,6 +46,12 @@
android:exported="false" android:exported="false"
android:screenOrientation="portrait" android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" /> tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".ui.guide.CleanGuideActivity"
android:exported="false"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity <activity
android:name=".ui.guide.GuideActivity" android:name=".ui.guide.GuideActivity"
android:exported="false" android:exported="false"
......
...@@ -4,14 +4,16 @@ package com.dumpster.cleaner.bean.config ...@@ -4,14 +4,16 @@ package com.dumpster.cleaner.bean.config
class AdConfigBean( class AdConfigBean(
var isAdShow: Boolean = true,//广告开关 var isAdShow: Boolean = true,//广告开关
var adSwitch: Boolean = true,//true 走admob,false走max
var taichiAdValue: Int = 1,//价值上报阀值 var taichiAdValue: Int = 1,//价值上报阀值
var adRatio: Int = 100,//价值上报随机控制 var adRatio: Int = 100,//价值上报随机控制
var numDisplayLimit: Int = -1,//展示次数限制 var numDisplayLimit: Int = -1,//展示次数限制
var numRequestLimit: Int = -1,//请求次数限制 var numRequestLimit: Int = -1,//请求次数限制
var numClickLimit: Int = -1,//点击次数限制 var numClickLimit: Int = -1,//点击次数限制
var timeInterval: Int = 10,//广告间隔秒
var timeInterval: Int = 10,//插页广告间隔秒
var timeIntervalOpen: Int = 0,//开屏广告间隔
var openAdLoading: Int = 15,//开屏广告拉取时间 var openAdLoading: Int = 15,//开屏广告拉取时间
var numNativeDisplayLimit: Int = -1,//原生展示次数限制 var numNativeDisplayLimit: Int = -1,//原生展示次数限制
......
...@@ -6,9 +6,9 @@ package com.dumpster.cleaner.bean.config ...@@ -6,9 +6,9 @@ package com.dumpster.cleaner.bean.config
*/ */
data class ConfigBean( data class ConfigBean(
var isInBlackList: Boolean = false, // var isInBlackList: Boolean = false,
val ut: Int = 0, val ut: Int = 0,
var vpnCanUse: Boolean = true, // var vpnCanUse: Boolean = true,
val adConfigBean: AdConfigBean = AdConfigBean(), val adConfigBean: AdConfigBean = AdConfigBean(),
val popupConfigBean: PopupConfigBean = PopupConfigBean(), val popupConfigBean: PopupConfigBean = PopupConfigBean(),
val vipConfigBean: VipConfigBean = VipConfigBean(), val vipConfigBean: VipConfigBean = VipConfigBean(),
......
...@@ -41,9 +41,9 @@ abstract class AdEvent { ...@@ -41,9 +41,9 @@ abstract class AdEvent {
fun adPulStart() { fun adPulStart() {
val obj = JSONObject() val obj = JSONObject()
obj.put("req_id", reqId)
obj.put("from", from)
obj.put("ad_unit", adUnit) obj.put("ad_unit", adUnit)
obj.put("from", from)
obj.put("req_id", reqId)
obj.put("ad_type", adUnit) obj.put("ad_type", adUnit)
EventUtils.event("ad_pull_start", ext = obj) EventUtils.event("ad_pull_start", ext = obj)
LogEx.logDebug(TAG, "ad_pull_start_$adUnit $obj") LogEx.logDebug(TAG, "ad_pull_start_$adUnit $obj")
......
package com.dumpster.cleaner.business.ads package com.dumpster.cleaner.business.ads
import android.app.Dialog 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>() { class AdState<T>() {
...@@ -34,20 +37,32 @@ class AdState<T>() { ...@@ -34,20 +37,32 @@ class AdState<T>() {
/** /**
* 广告已经展示 * 广告已经展示
*/ */
fun onAdDisplayed() { fun onAdDisplayed(adsType: AdsType) {
currentAd = null currentAd = null
currentAdEvent = null currentAdEvent = null
adDialog?.dismiss() adDialog?.dismiss()
adDialog = null 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>() { ...@@ -59,14 +74,14 @@ class AdState<T>() {
currentAdEvent = null currentAdEvent = null
} }
fun onAdLoaded(ad: T?, adEvent: AdEvent?) { fun loadStart(adEvent: AdEvent) {
//这里可能提前设置,所有可以不设置,max回调的类型可能不同 loadingAd = true
if (ad != null) { currentAdEvent = adEvent
currentAd = ad }
}
if (adEvent != null) { fun onAdLoaded(ad: T?) {
currentAdEvent = adEvent currentAd = ad
}
loadingAd = false loadingAd = false
lastLoadTime = System.currentTimeMillis() lastLoadTime = System.currentTimeMillis()
} }
...@@ -81,4 +96,5 @@ class AdState<T>() { ...@@ -81,4 +96,5 @@ class AdState<T>() {
fun adAvailable() = fun adAvailable() =
currentAd != null || ((System.currentTimeMillis() - lastLoadTime) / 1000 / 60).toInt() < 30 currentAd != null || ((System.currentTimeMillis() - lastLoadTime) / 1000 / 60).toInt() < 30
} }
...@@ -18,10 +18,10 @@ import com.dumpster.cleaner.business.ads.admob.AdInterMgr ...@@ -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.AdNativeMgr
import com.dumpster.cleaner.business.ads.admob.AdOpenMgr import com.dumpster.cleaner.business.ads.admob.AdOpenMgr
import com.dumpster.cleaner.business.ads.admob.AdmobEvent import com.dumpster.cleaner.business.ads.admob.AdmobEvent
import com.dumpster.cleaner.business.ads.applovin.AdMaxEvent //import com.dumpster.cleaner.business.ads.applovin.AdMaxEvent
import com.dumpster.cleaner.business.ads.applovin.MaxInsertMgr //import com.dumpster.cleaner.business.ads.applovin.MaxInsertMgr
import com.dumpster.cleaner.business.ads.applovin.MaxNativeMgr //import com.dumpster.cleaner.business.ads.applovin.MaxNativeMgr
import com.dumpster.cleaner.business.ads.applovin.MaxOpenMgr //import com.dumpster.cleaner.business.ads.applovin.MaxOpenMgr
import com.dumpster.cleaner.business.helper.EventUtils import com.dumpster.cleaner.business.helper.EventUtils
import com.dumpster.cleaner.utils.AppPreferences import com.dumpster.cleaner.utils.AppPreferences
import com.dumpster.cleaner.utils.LogEx import com.dumpster.cleaner.utils.LogEx
...@@ -49,15 +49,15 @@ object AdsMgr { ...@@ -49,15 +49,15 @@ object AdsMgr {
private val adBannerMgr by lazy { private val adBannerMgr by lazy {
AdBannerMgr() AdBannerMgr()
} }
private val maxOpenMgr by lazy { // private val maxOpenMgr by lazy {
MaxOpenMgr() // MaxOpenMgr()
} // }
private val maxInsertMgr by lazy { // private val maxInsertMgr by lazy {
MaxInsertMgr() // MaxInsertMgr()
} // }
private val maxNativeMgr by lazy { // private val maxNativeMgr by lazy {
MaxNativeMgr() // MaxNativeMgr()
} // }
/** /**
* 是否初始化 * 是否初始化
...@@ -87,12 +87,12 @@ object AdsMgr { ...@@ -87,12 +87,12 @@ object AdsMgr {
*/ */
fun init(context: Context) { fun init(context: Context) {
if (configBean.isInBlackList) { // if (configBean.isInBlackList) {
EventUtils.event("isInBlackList", value = "isInBlackList=${configBean.isInBlackList}") // EventUtils.event("isInBlackList", value = "isInBlackList=${configBean.isInBlackList}")
return // return
} // }
initAdmob(context) initAdmob(context)
initMax(context) // initMax(context)
} }
...@@ -106,7 +106,7 @@ object AdsMgr { ...@@ -106,7 +106,7 @@ object AdsMgr {
EventUtils.event("AdmobInit", "AdmobInit=$isAdmobInit") EventUtils.event("AdmobInit", "AdmobInit=$isAdmobInit")
// context.toast("admob init") // context.toast("admob init")
if (adsConfigBean.adSwitch) { if (true) {
admobInitCallBack?.invoke() admobInitCallBack?.invoke()
admobInitCallBack = null admobInitCallBack = null
adNativeMgr.loadAd(context, AdmobEvent("nativeAd", context::class.java.simpleName)) adNativeMgr.loadAd(context, AdmobEvent("nativeAd", context::class.java.simpleName))
...@@ -117,38 +117,38 @@ object AdsMgr { ...@@ -117,38 +117,38 @@ object AdsMgr {
} }
private fun initMax(context: Context) = kotlin.runCatching { // private fun initMax(context: Context) = kotlin.runCatching {
if (isMaxInit) return@runCatching // if (isMaxInit) return@runCatching
val executor = Executors.newSingleThreadExecutor() // val executor = Executors.newSingleThreadExecutor()
//
executor.execute { // executor.execute {
val currentGaid = AdvertisingIdClient.getAdvertisingIdInfo(context).id // val currentGaid = AdvertisingIdClient.getAdvertisingIdInfo(context).id
AppPreferences.getInstance().getString("gid", currentGaid) // AppPreferences.getInstance().getString("gid", currentGaid)
//
val build = AppLovinSdkInitializationConfiguration // val build = AppLovinSdkInitializationConfiguration
.builder(GlobalConfig.KEY_MAX, context) // .builder(GlobalConfig.KEY_MAX, context)
//
build.mediationProvider = AppLovinMediationProvider.MAX // build.mediationProvider = AppLovinMediationProvider.MAX
if (BuildConfig.DEBUG) { // if (BuildConfig.DEBUG) {
build.testDeviceAdvertisingIds = Collections.singletonList(currentGaid) // build.testDeviceAdvertisingIds = Collections.singletonList(currentGaid)
} // }
val initConfig = build.build() // val initConfig = build.build()
runCatching { // runCatching {
AppLovinSdk.getInstance(context).initialize(initConfig) { // AppLovinSdk.getInstance(context).initialize(initConfig) {
isMaxInit = true // isMaxInit = true
// maxOpenMgr.loadAd(context) //// maxOpenMgr.loadAd(context)
if (!adsConfigBean.adSwitch) { // if (!adsConfigBean.adSwitch) {
// maxInsertMgr.loadAd(context, AdMaxEvent("interAd", context::class.java.simpleName)) //// maxInsertMgr.loadAd(context, AdMaxEvent("interAd", context::class.java.simpleName))
context.toast("max init") // context.toast("max init")
maxInitCallBack?.invoke() // maxInitCallBack?.invoke()
maxInitCallBack = null // maxInitCallBack = null
} // }
} // }
} // }
//
} // }
//
} // }
var admobInitCallBack: (() -> Unit)? = null var admobInitCallBack: (() -> Unit)? = null
var maxInitCallBack: (() -> Unit)? = null var maxInitCallBack: (() -> Unit)? = null
...@@ -172,14 +172,14 @@ object AdsMgr { ...@@ -172,14 +172,14 @@ object AdsMgr {
return return
} }
if (configBean.isInBlackList) { // if (configBean.isInBlackList) {
EventUtils.event("isInBlackList", "isInBlackList=${configBean.isInBlackList}") // EventUtils.event("isInBlackList", "isInBlackList=${configBean.isInBlackList}")
showCallBack?.failed() // showCallBack?.failed()
return // return
} // }
val from = activity::class.java.simpleName val from = activity::class.java.simpleName
if (adsConfigBean.adSwitch) { if (true) {
val admobEvent = AdmobEvent("openAd", from).apply { this.isUnLimit = isUnLimit } val admobEvent = AdmobEvent("openAd", from).apply { this.isUnLimit = isUnLimit }
if (isAdmobInit) { if (isAdmobInit) {
adOpenMgr.show(activity, admobEvent, showCallBack) adOpenMgr.show(activity, admobEvent, showCallBack)
...@@ -189,13 +189,13 @@ object AdsMgr { ...@@ -189,13 +189,13 @@ object AdsMgr {
adOpenMgr.show(activity, admobEvent, showCallBack) adOpenMgr.show(activity, admobEvent, showCallBack)
} }
} else { } else {
if (isMaxInit) { // if (isMaxInit) {
maxOpenMgr.show(activity, isUnLimit, AdMaxEvent("openAd", from), showCallBack) // maxOpenMgr.show(activity, isUnLimit, AdMaxEvent("openAd", from), showCallBack)
} else { // } else {
maxInitCallBack = { // maxInitCallBack = {
maxOpenMgr.show(activity, isUnLimit, AdMaxEvent("openAd", from), showCallBack) // maxOpenMgr.show(activity, isUnLimit, AdMaxEvent("openAd", from), showCallBack)
} // }
} // }
} }
} }
...@@ -219,17 +219,16 @@ object AdsMgr { ...@@ -219,17 +219,16 @@ object AdsMgr {
return return
} }
if (configBean.isInBlackList) { // if (configBean.isInBlackList) {
EventUtils.event("isInBlackList", configBean.isInBlackList.toString()) // EventUtils.event("isInBlackList", configBean.isInBlackList.toString())
showCallBack?.failed() // showCallBack?.failed()
return // return
} // }
LogEx.logDebug("showAd", "adSwitch=${adsConfigBean.adSwitch}")
val from = activity::class.java.simpleName val from = activity::class.java.simpleName
if (adsConfigBean.adSwitch) { if (true) {
adInterMgr.show(activity, AdmobEvent("interAd", from).apply { this.isUnLimit = isUnLimit }, showCallBack) adInterMgr.show(activity, AdmobEvent("interAd", from).apply { this.isUnLimit = isUnLimit }, showCallBack)
} else { } else {
maxInsertMgr.show(activity, isUnLimit, AdMaxEvent("interAd", from), showCallBack) // maxInsertMgr.show(activity, isUnLimit, AdMaxEvent("interAd", from), showCallBack)
} }
} }
...@@ -250,16 +249,16 @@ object AdsMgr { ...@@ -250,16 +249,16 @@ object AdsMgr {
return return
} }
nativeView.visibility = View.VISIBLE nativeView.visibility = View.VISIBLE
if (configBean.isInBlackList) { // if (configBean.isInBlackList) {
EventUtils.event("isInBlackList", configBean.isInBlackList.toString()) // EventUtils.event("isInBlackList", configBean.isInBlackList.toString())
return // return
} // }
val showNative = { val showNative = {
if (adsConfigBean.adSwitch) { if (true) {
adNativeMgr.show(AdmobEvent("nativeAd", "nativeAd"), nativeView, layout, nativeCallBack) adNativeMgr.show(AdmobEvent("nativeAd", "nativeAd"), nativeView, layout, nativeCallBack)
} else { } else {
maxNativeMgr.show(AdMaxEvent("nativeAd", "nativeAd"), nativeView, layout, nativeCallBack) // maxNativeMgr.show(AdMaxEvent("nativeAd", "nativeAd"), nativeView, layout, nativeCallBack)
} }
} }
...@@ -282,11 +281,11 @@ object AdsMgr { ...@@ -282,11 +281,11 @@ object AdsMgr {
return return
} }
parent.visibility = View.VISIBLE parent.visibility = View.VISIBLE
if (configBean.isInBlackList) { // if (configBean.isInBlackList) {
EventUtils.event("isInBlackList", configBean.isInBlackList.toString()) // EventUtils.event("isInBlackList", configBean.isInBlackList.toString())
return // return
} // }
if (adsConfigBean.adSwitch) { if (true) {
adBannerMgr.show(parent, collapsible, adClose) adBannerMgr.show(parent, collapsible, adClose)
} }
} }
......
...@@ -151,26 +151,48 @@ object LimitUtils { ...@@ -151,26 +151,48 @@ object LimitUtils {
/** /**
* 开屏和插页广告的显示间隔限制 * 开屏限制
*/ */
fun isIntervalLimited(adEvent: AdEvent): Boolean { fun isIntervalOpenLimit(adEvent: AdEvent): Boolean {
val flag = ((System.currentTimeMillis() - openInterLastShowTime) / 1000).toInt() < (AdConfigBean.adsConfigBean.timeInterval) val flag = ((System.currentTimeMillis() - openLastShowTime) / 1000).toInt() < (AdConfigBean.adsConfigBean.timeIntervalOpen)
if (flag) { if (flag) {
adEvent.adShowError("ad in timeInterval") adEvent.adShowError("ad in timeInterval")
} }
return flag 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() { get() {
return AppPreferences.getInstance().getLong("openInterLastShowTime", field) return AppPreferences.getInstance().getLong("openLastShowTime", field)
} }
set(value) { set(value) {
field = 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 ...@@ -4,7 +4,6 @@ import android.os.Bundle
import android.view.ViewGroup import android.view.ViewGroup
import android.view.ViewTreeObserver import android.view.ViewTreeObserver
import com.dumpster.cleaner.GlobalConfig 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.AdsType
import com.dumpster.cleaner.business.ads.LimitUtils import com.dumpster.cleaner.business.ads.LimitUtils
import com.dumpster.cleaner.business.ads.admob.AdmobEvent.AdmobOnPaidEventListener import com.dumpster.cleaner.business.ads.admob.AdmobEvent.AdmobOnPaidEventListener
...@@ -26,9 +25,9 @@ class AdBannerMgr { ...@@ -26,9 +25,9 @@ class AdBannerMgr {
fun show(parent: ViewGroup, collapsible: Boolean, adClose: (() -> Unit)? = null) { fun show(parent: ViewGroup, collapsible: Boolean, adClose: (() -> Unit)? = null) {
if (!AdConfigBean.adsConfigBean.adSwitch) { // if (!AdConfigBean.adsConfigBean.adSwitch) {
return // return
} // }
val admobEvent = AdmobEvent("banner", "banner") val admobEvent = AdmobEvent("banner", "banner")
if (!LimitUtils.isAdShow(AdsType.BANNER, admobEvent)) { if (!LimitUtils.isAdShow(AdsType.BANNER, admobEvent)) {
......
...@@ -11,6 +11,7 @@ import com.dumpster.cleaner.business.ads.AdEvent ...@@ -11,6 +11,7 @@ import com.dumpster.cleaner.business.ads.AdEvent
import com.dumpster.cleaner.business.ads.AdState import com.dumpster.cleaner.business.ads.AdState
import com.dumpster.cleaner.business.ads.AdsShowCallBack import com.dumpster.cleaner.business.ads.AdsShowCallBack
import com.dumpster.cleaner.business.ads.AdsType 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.LimitUtils
import com.dumpster.cleaner.business.ads.admob.AdmobEvent.AdmobOnPaidEventListener import com.dumpster.cleaner.business.ads.admob.AdmobEvent.AdmobOnPaidEventListener
import com.dumpster.cleaner.utils.LogEx import com.dumpster.cleaner.utils.LogEx
...@@ -32,7 +33,7 @@ class AdInterMgr { ...@@ -32,7 +33,7 @@ class AdInterMgr {
//正在加载回调 //正在加载回调
private var loadingCallBack: (() -> Unit)? = null private var loadingCallBack: ((flag: Boolean) -> Unit)? = null
fun show( fun show(
activity: Activity, activity: Activity,
...@@ -44,16 +45,15 @@ class AdInterMgr { ...@@ -44,16 +45,15 @@ class AdInterMgr {
return return
} }
val nowAdEvent = adEvent
//currentAdEvent!=null 表示有缓存广告,关联reqId //currentAdEvent!=null 表示有缓存广告,关联reqId
adState.currentAdEvent?.let { nowAdEvent.reqId = it.reqId } adState.currentAdEvent?.let { adEvent.reqId = it.reqId }
if (!nowAdEvent.isUnLimit) { if (!adEvent.isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.INSERT, nowAdEvent)) { if (!LimitUtils.isAdShow(AdsType.INSERT, adEvent)) {
showCallBack?.failed(2) showCallBack?.failed(2)
return return
} }
if (LimitUtils.isIntervalLimited(nowAdEvent)) { if (LimitUtils.isIntervalInterLimit(adEvent)) {
showCallBack?.failed(3) showCallBack?.failed(3)
return return
} }
...@@ -69,24 +69,29 @@ class AdInterMgr { ...@@ -69,24 +69,29 @@ class AdInterMgr {
adState.adDialog?.dismiss() adState.adDialog?.dismiss()
} }
nowAdEvent.adPrepareShow() adEvent.adPrepareShow()
LogEx.logDebug(adEvent.TAG, "needLoad=$needLoad") LogEx.logDebug(adEvent.TAG, "needLoad=$needLoad")
if (needLoad) { if (needLoad) {
if (!adState.loadingAd) { if (!adState.loadingAd) {
LogEx.logDebug(adEvent.TAG, "inter adState !loadingAd") LogEx.logDebug(adEvent.TAG, "inter adState !loadingAd")
loadAd(activity, nowAdEvent) { loadAd(activity, adEvent) {
showReadyAd(activity, nowAdEvent) if (it) {
showReadyAd(activity, adEvent)
} else {
showCallBack?.adFailed()
}
} }
} else { } else {
LogEx.logDebug(adEvent.TAG, "inter adState is loadingAd") LogEx.logDebug(adEvent.TAG, "inter adState is loadingAd")
loadingCallBack = { loadingCallBack = {
showReadyAd(activity, nowAdEvent) showReadyAd(activity, adEvent)
} }
} }
} else { } else {
LogEx.logDebug(adEvent.TAG, "inter ad ready") LogEx.logDebug(adEvent.TAG, "inter ad ready")
showReadyAd(activity, nowAdEvent) showReadyAd(activity, adEvent)
} }
} }
...@@ -113,7 +118,7 @@ class AdInterMgr { ...@@ -113,7 +118,7 @@ class AdInterMgr {
admobEvent.showAd(responseInfo, ac) admobEvent.showAd(responseInfo, ac)
adState.onAdDisplayed() adState.onAdDisplayed(OPEN)
showCallBack?.show() showCallBack?.show()
LimitUtils.addDisplayNum() LimitUtils.addDisplayNum()
...@@ -132,7 +137,7 @@ class AdInterMgr { ...@@ -132,7 +137,7 @@ class AdInterMgr {
override fun onAdDismissedFullScreenContent() { override fun onAdDismissedFullScreenContent() {
super.onAdDismissedFullScreenContent() super.onAdDismissedFullScreenContent()
adState.onAdHidden() adState.onAdHidden(OPEN)
showCallBack?.close() showCallBack?.close()
showCallBack = null showCallBack = null
...@@ -160,7 +165,7 @@ class AdInterMgr { ...@@ -160,7 +165,7 @@ class AdInterMgr {
fun loadAd( fun loadAd(
context: Context, context: Context,
adEvent: AdEvent, adEvent: AdEvent,
loadCallBack: (() -> Unit)? = null loadCallBack: ((flag: Boolean) -> Unit)? = null
) { ) {
if (!adEvent.isUnLimit) { if (!adEvent.isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.INSERT, adEvent)) { if (!LimitUtils.isAdShow(AdsType.INSERT, adEvent)) {
...@@ -172,14 +177,12 @@ class AdInterMgr { ...@@ -172,14 +177,12 @@ class AdInterMgr {
} }
//避免无效预加载 //避免无效预加载
if (adState.loadingAd && loadCallBack == null && loadingCallBack == null) { if (adState.loadingAd) {
//容错机制
adState.loadingAd = false
return return
} }
adState.loadingAd = true
adEvent.adPulStart() adEvent.adPulStart()
adState.loadStart(adEvent)
InterstitialAd.load( InterstitialAd.load(
context, GlobalConfig.ID_ADMOB_INTER, AdRequest.Builder().build(), context, GlobalConfig.ID_ADMOB_INTER, AdRequest.Builder().build(),
...@@ -187,10 +190,10 @@ class AdInterMgr { ...@@ -187,10 +190,10 @@ class AdInterMgr {
override fun onAdLoaded(ad: InterstitialAd) { override fun onAdLoaded(ad: InterstitialAd) {
val event = (adEvent as AdmobEvent) val event = (adEvent as AdmobEvent)
ad.onPaidEventListener = AdmobOnPaidEventListener(ad, adEvent.scope) ad.onPaidEventListener = AdmobOnPaidEventListener(ad, adEvent.scope)
adState.onAdLoaded(ad, adEvent) adState.onAdLoaded(ad)
loadCallBack?.invoke() loadCallBack?.invoke(true)
loadingCallBack?.invoke() loadingCallBack?.invoke(true)
loadingCallBack = null loadingCallBack = null
LimitUtils.addRequestNum() LimitUtils.addRequestNum()
...@@ -199,11 +202,14 @@ class AdInterMgr { ...@@ -199,11 +202,14 @@ class AdInterMgr {
override fun onAdFailedToLoad(loadAdError: LoadAdError) { override fun onAdFailedToLoad(loadAdError: LoadAdError) {
adState.onAdLoadFailed() adState.onAdLoadFailed()
if (loadCallBack != null) { if (loadCallBack != null) {
adState.onAdDisplayFailed() adState.onAdDisplayFailed()
} }
showCallBack?.adFailed() loadCallBack?.invoke(false)
showCallBack = null loadingCallBack?.invoke(false)
loadingCallBack = null
(adEvent as AdmobEvent).pullAd(loadAdError.responseInfo, loadAdError) (adEvent as AdmobEvent).pullAd(loadAdError.responseInfo, loadAdError)
} }
......
...@@ -8,6 +8,7 @@ import com.dumpster.cleaner.business.ads.AdEvent ...@@ -8,6 +8,7 @@ import com.dumpster.cleaner.business.ads.AdEvent
import com.dumpster.cleaner.business.ads.AdState import com.dumpster.cleaner.business.ads.AdState
import com.dumpster.cleaner.business.ads.AdsShowCallBack import com.dumpster.cleaner.business.ads.AdsShowCallBack
import com.dumpster.cleaner.business.ads.AdsType 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.LimitUtils
import com.dumpster.cleaner.business.ads.admob.AdmobEvent.AdmobOnPaidEventListener import com.dumpster.cleaner.business.ads.admob.AdmobEvent.AdmobOnPaidEventListener
import com.dumpster.cleaner.utils.LogEx import com.dumpster.cleaner.utils.LogEx
...@@ -27,7 +28,7 @@ class AdOpenMgr { ...@@ -27,7 +28,7 @@ class AdOpenMgr {
private var showCallBack: AdsShowCallBack? = null private var showCallBack: AdsShowCallBack? = null
//正在加载回调 //正在加载回调
private var loadingCallBack: (() -> Unit)? = null private var loadingCallBack: ((flag: Boolean) -> Unit)? = null
fun show( fun show(
activity: Activity, activity: Activity,
...@@ -38,15 +39,14 @@ class AdOpenMgr { ...@@ -38,15 +39,14 @@ class AdOpenMgr {
return return
} }
val nowAdEvent = adEvent adState.currentAdEvent?.let { adEvent.reqId = it.reqId }
adState.currentAdEvent?.let { nowAdEvent.reqId = it.reqId }
if (!nowAdEvent.isUnLimit) { if (!adEvent.isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.OPEN, nowAdEvent)) { if (!LimitUtils.isAdShow(AdsType.OPEN, adEvent)) {
showCallBack?.failed() showCallBack?.failed()
return return
} }
if (LimitUtils.isIntervalLimited(nowAdEvent)) { if (LimitUtils.isIntervalOpenLimit(adEvent)) {
showCallBack?.failed() showCallBack?.failed()
return return
} }
...@@ -55,26 +55,36 @@ class AdOpenMgr { ...@@ -55,26 +55,36 @@ class AdOpenMgr {
val needLoad = !adState.adAvailable() val needLoad = !adState.adAvailable()
this.showCallBack = showCallBack this.showCallBack = showCallBack
nowAdEvent.adPrepareShow() adEvent.adPrepareShow()
if (needLoad) { if (needLoad) {
if (!adState.loadingAd) { if (!adState.loadingAd) {
LogEx.logDebug(adEvent.TAG, "open adState !loadingAd") LogEx.logDebug(adEvent.TAG, "open adState !loadingAd")
loadAd(activity, adEvent) { loadAd(activity, adEvent) {
showReadyAd(activity) if (it) {
showReadyAd(activity, adEvent)
} else {
showCallBack?.adFailed()
}
} }
} else { } else {
LogEx.logDebug(adEvent.TAG, "open adState is loadingAd") LogEx.logDebug(adEvent.TAG, "open adState is loadingAd")
loadingCallBack = { loadingCallBack = {
showReadyAd(activity) if (it) {
showReadyAd(activity, adEvent)
} else {
showCallBack?.adFailed()
}
} }
} }
} else { } else {
LogEx.logDebug(adEvent.TAG, "open ad ready") 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) { if (ac.isFinishing || ac.isDestroyed || adState.currentAd == null) {
LogEx.logDebug(TAG, "showReadyAd ac=null isFinishing isDestroyed") LogEx.logDebug(TAG, "showReadyAd ac=null isFinishing isDestroyed")
...@@ -83,16 +93,15 @@ class AdOpenMgr { ...@@ -83,16 +93,15 @@ class AdOpenMgr {
adState.currentAd?.run { adState.currentAd?.run {
val adEvent = adState.currentAdEvent as AdmobEvent?
fullScreenContentCallback = object : FullScreenContentCallback() { fullScreenContentCallback = object : FullScreenContentCallback() {
override fun onAdShowedFullScreenContent() { override fun onAdShowedFullScreenContent() {
adEvent?.showAd(this@run.responseInfo, ac) admobEvent.showAd(this@run.responseInfo, ac)
showCallBack?.show() showCallBack?.show()
adState.onAdDisplayed() adState.onAdDisplayed(INSERT)
//计数 //计数
LimitUtils.addDisplayNum() LimitUtils.addDisplayNum()
...@@ -105,7 +114,7 @@ class AdOpenMgr { ...@@ -105,7 +114,7 @@ class AdOpenMgr {
showCallBack = null showCallBack = null
adState.onAdDisplayFailed() adState.onAdDisplayFailed()
adEvent?.adShowError(adError) admobEvent.adShowError(adError)
} }
...@@ -115,15 +124,14 @@ class AdOpenMgr { ...@@ -115,15 +124,14 @@ class AdOpenMgr {
showCallBack?.close() showCallBack?.close()
showCallBack = null showCallBack = null
adState.onAdHidden() adState.onAdHidden(INSERT)
//预加载,“Timeout for show call succeed.”预加载的广告大概率, //预加载,“Timeout for show call succeed.”预加载的广告大概率,
loadAd(MyApplication.appContext, AdmobEvent("openAd", "preload")) loadAd(MyApplication.appContext, AdmobEvent("openAd", "preload"))
} }
override fun onAdClicked() { override fun onAdClicked() {
adEvent?.clickAd(this@run.responseInfo) admobEvent.clickAd(this@run.responseInfo)
//计数 //计数
LimitUtils.addClickNum() LimitUtils.addClickNum()
} }
...@@ -135,7 +143,7 @@ class AdOpenMgr { ...@@ -135,7 +143,7 @@ class AdOpenMgr {
fun loadAd( fun loadAd(
context: Context, context: Context,
adEvent: AdEvent, adEvent: AdEvent,
loadCallBack: (() -> Unit)? = null loadCallBack: ((flag: Boolean) -> Unit)? = null
) { ) {
if (!adEvent.isUnLimit) { if (!adEvent.isUnLimit) {
...@@ -148,14 +156,12 @@ class AdOpenMgr { ...@@ -148,14 +156,12 @@ class AdOpenMgr {
} }
//避免无效预加载 //避免无效预加载
if (adState.loadingAd && loadCallBack == null && loadingCallBack == null) { if (adState.loadingAd) {
//容错机制
adState.loadingAd = false
return return
} }
adState.loadingAd = true
adEvent.adPulStart() adEvent.adPulStart()
adState.loadStart(adEvent)
AppOpenAd.load( AppOpenAd.load(
context, context,
...@@ -163,21 +169,27 @@ class AdOpenMgr { ...@@ -163,21 +169,27 @@ class AdOpenMgr {
AdRequest.Builder().build(), AdRequest.Builder().build(),
object : AppOpenAd.AppOpenAdLoadCallback() { object : AppOpenAd.AppOpenAdLoadCallback() {
override fun onAdLoaded(appOpenAd: AppOpenAd) { override fun onAdLoaded(appOpenAd: AppOpenAd) {
adState.onAdLoaded(appOpenAd, adEvent) LogEx.logDebug(adEvent.TAG, "open onAdLoaded loadAd")
loadCallBack?.invoke() appOpenAd.onPaidEventListener = AdmobOnPaidEventListener(appOpenAd, adEvent.scope)
loadingCallBack?.invoke() adState.onAdLoaded(appOpenAd)
loadCallBack?.invoke(true)
loadingCallBack?.invoke(true)
loadingCallBack = null loadingCallBack = null
(adEvent as AdmobEvent).pullAd(appOpenAd.responseInfo)
appOpenAd.onPaidEventListener = AdmobOnPaidEventListener(appOpenAd, adEvent.scope)
LimitUtils.addRequestNum() LimitUtils.addRequestNum()
(adEvent as AdmobEvent).pullAd(appOpenAd.responseInfo)
} }
override fun onAdFailedToLoad(loadAdError: LoadAdError) { override fun onAdFailedToLoad(loadAdError: LoadAdError) {
showCallBack?.adFailed() LogEx.logDebug(adEvent.TAG, "open onAdFailedToLoad loadAd")
showCallBack = null
adState.onAdLoadFailed() adState.onAdLoadFailed()
loadCallBack?.invoke(false)
loadingCallBack?.invoke(false)
loadingCallBack = null
(adEvent as AdmobEvent).pullAd(loadAdError.responseInfo, loadAdError) (adEvent as AdmobEvent).pullAd(loadAdError.responseInfo, loadAdError)
} }
} }
......
...@@ -49,6 +49,8 @@ class AdmobEvent : AdEvent { ...@@ -49,6 +49,8 @@ class AdmobEvent : AdEvent {
) { ) {
var key = "ad_pull" var key = "ad_pull"
val obj = JSONObject() val obj = JSONObject()
obj.put("ad_unit", adUnit)
obj.put("from", from)
obj.put("req_id", reqId) obj.put("req_id", reqId)
if (responseInfo != null) { if (responseInfo != null) {
val response = responseInfo.adapterResponses.getOrNull(0) val response = responseInfo.adapterResponses.getOrNull(0)
...@@ -65,8 +67,6 @@ class AdmobEvent : AdEvent { ...@@ -65,8 +67,6 @@ class AdmobEvent : AdEvent {
obj.put("session_id", responseInfo.responseId) obj.put("session_id", responseInfo.responseId)
} }
obj.put("networkname", responseInfo?.mediationAdapterClassName) obj.put("networkname", responseInfo?.mediationAdapterClassName)
obj.put("ad_unit", adUnit)
obj.put("from", from)
if (error == null) { if (error == null) {
obj.put("status", "1") obj.put("status", "1")
} else { } else {
...@@ -75,7 +75,7 @@ class AdmobEvent : AdEvent { ...@@ -75,7 +75,7 @@ class AdmobEvent : AdEvent {
key = "ad_pull_error" key = "ad_pull_error"
} }
EventUtils.event(key, ext = obj) EventUtils.event(key, ext = obj)
LogEx.logDebug(TAG, "ad_pull obj=$obj") LogEx.logDebug(TAG, "${key}_$adUnit obj=$obj")
} }
......
package com.dumpster.cleaner.business.ads.applovin //package com.dumpster.cleaner.business.ads.applovin
//
import android.os.Bundle //import android.os.Bundle
import com.applovin.mediation.MaxAd //import com.applovin.mediation.MaxAd
import com.applovin.mediation.MaxAdRevenueListener //import com.applovin.mediation.MaxAdRevenueListener
import com.applovin.mediation.MaxError //import com.applovin.mediation.MaxError
import com.applovin.sdk.AppLovinSdk //import com.applovin.sdk.AppLovinSdk
import com.dumpster.cleaner.MyApplication //import com.dumpster.cleaner.MyApplication
import com.dumpster.cleaner.business.ads.AdEvent //import com.dumpster.cleaner.business.ads.AdEvent
import com.dumpster.cleaner.business.ads.taichiPref //import com.dumpster.cleaner.business.ads.taichiPref
import com.dumpster.cleaner.business.ads.taichiSharedPreferencesEditor //import com.dumpster.cleaner.business.ads.taichiSharedPreferencesEditor
import com.dumpster.cleaner.business.helper.EventUtils //import com.dumpster.cleaner.business.helper.EventUtils
import com.dumpster.cleaner.utils.LogEx.logDebug //import com.dumpster.cleaner.utils.LogEx.logDebug
import com.facebook.appevents.AppEventsConstants //import com.facebook.appevents.AppEventsConstants
import com.facebook.appevents.AppEventsLogger //import com.facebook.appevents.AppEventsLogger
import com.google.firebase.analytics.FirebaseAnalytics //import com.google.firebase.analytics.FirebaseAnalytics
import org.json.JSONObject //import org.json.JSONObject
//
//
class AdMaxEvent : AdEvent { //class AdMaxEvent : AdEvent {
//
override val TAG: String = "AdMaxEvent" // override val TAG: String = "AdMaxEvent"
//
constructor(adUnit: String, from: String) : super() { // constructor(adUnit: String, from: String) : super() {
this.adUnit = adUnit // this.adUnit = adUnit
this.from = from // this.from = from
} // }
//
fun pullAd( // fun pullAd(
ad: MaxAd?, // ad: MaxAd?,
error: MaxError? = null // error: MaxError? = null
) { // ) {
val obj = JSONObject() // val obj = JSONObject()
obj.put("UnitId", ad?.adUnitId) // obj.put("UnitId", ad?.adUnitId)
obj.put("ad_unit", adUnit) // obj.put("ad_unit", adUnit)
obj.put( // obj.put(
"creativeId", // "creativeId",
ad?.creativeId // ad?.creativeId
) // )
obj.put("req_id", reqId) // obj.put("req_id", reqId)
obj.put("from", from) // obj.put("from", from)
obj.put("status", if (ad == null) "0" else "1") // obj.put("status", if (ad == null) "0" else "1")
obj.put("networkname", ad?.networkName) // obj.put("networkname", ad?.networkName)
obj.put("placement", ad?.placement) // obj.put("placement", ad?.placement)
obj.put("networkplacement", ad?.networkPlacement) // obj.put("networkplacement", ad?.networkPlacement)
obj.put("latency", ad?.requestLatencyMillis) // obj.put("latency", ad?.requestLatencyMillis)
obj.put("valueMicros", ad?.revenue) // obj.put("valueMicros", ad?.revenue)
if (error == null) { // if (error == null) {
obj.put("status", "1") // obj.put("status", "1")
} else { // } else {
obj.put("errMsg", error) // obj.put("errMsg", error)
obj.put("status", "2") // obj.put("status", "2")
} // }
EventUtils.event("ad_pull", ext = obj) // EventUtils.event("ad_pull", ext = obj)
logDebug(TAG, "ad_pull $obj") // logDebug(TAG, "ad_pull $obj")
} // }
//
fun clickAd(ad: MaxAd?) { // fun clickAd(ad: MaxAd?) {
//
val obj = JSONObject() // val obj = JSONObject()
obj.put("UnitId", ad?.adUnitId) // obj.put("UnitId", ad?.adUnitId)
obj.put("ad_unit", adUnit) // obj.put("ad_unit", adUnit)
obj.put( // obj.put(
"creativeId", // "creativeId",
ad?.creativeId // ad?.creativeId
) // )
obj.put("networkname", ad?.networkName) // obj.put("networkname", ad?.networkName)
obj.put("placement", ad?.placement) // obj.put("placement", ad?.placement)
obj.put("networkplacement", ad?.networkPlacement) // obj.put("networkplacement", ad?.networkPlacement)
obj.put("latency", ad?.requestLatencyMillis) // obj.put("latency", ad?.requestLatencyMillis)
obj.put("valueMicros", ad?.revenue) // obj.put("valueMicros", ad?.revenue)
if (!adUnit.equals("nativeAd")) { // if (!adUnit.equals("nativeAd")) {
EventUtils.event("ad_click", ext = obj) // EventUtils.event("ad_click", ext = obj)
} else { // } else {
EventUtils.event("ad_click", ext = obj) // EventUtils.event("ad_click", ext = obj)
} // }
//
} // }
//
fun showAd(ad: MaxAd?, activity: String?) { // fun showAd(ad: MaxAd?, activity: String?) {
val obj = JSONObject() // val obj = JSONObject()
obj.put("UnitId", ad?.adUnitId) // obj.put("UnitId", ad?.adUnitId)
obj.put("ad_unit", adUnit) // obj.put("ad_unit", adUnit)
obj.put( // obj.put(
"creativeId", // "creativeId",
ad?.creativeId // ad?.creativeId
) // )
obj.put("networkname", ad?.networkName) // obj.put("networkname", ad?.networkName)
obj.put("placement", ad?.placement) // obj.put("placement", ad?.placement)
obj.put("networkplacement", ad?.networkPlacement) // obj.put("networkplacement", ad?.networkPlacement)
obj.put("latency", ad?.requestLatencyMillis) // obj.put("latency", ad?.requestLatencyMillis)
obj.put("valueMicros", ad?.revenue) // obj.put("valueMicros", ad?.revenue)
obj.put("from", activity) // obj.put("from", activity)
obj.put("mediation", "applovin") // obj.put("mediation", "applovin")
if (adUnit != "nativeAd") { // if (adUnit != "nativeAd") {
EventUtils.event("ad_show", ext = obj) // EventUtils.event("ad_show", ext = obj)
} else { // } else {
EventUtils.event("ad_show", ext = obj) // EventUtils.event("ad_show", ext = obj)
} // }
//
} // }
//
//
class EventOnPaidEventListener : MaxAdRevenueListener { // class EventOnPaidEventListener : MaxAdRevenueListener {
override fun onAdRevenuePaid(ad: MaxAd) { // override fun onAdRevenuePaid(ad: MaxAd) {
val params = Bundle() // val params = Bundle()
val currentImpressionRevenue: Double = ad.revenue // In USD // val currentImpressionRevenue: Double = ad.revenue // In USD
val mFirebaseAnalytics = FirebaseAnalytics.getInstance(MyApplication.appContext) // val mFirebaseAnalytics = FirebaseAnalytics.getInstance(MyApplication.appContext)
params.putString(FirebaseAnalytics.Param.AD_PLATFORM, "appLovin") // params.putString(FirebaseAnalytics.Param.AD_PLATFORM, "appLovin")
params.putString(FirebaseAnalytics.Param.AD_SOURCE, ad.networkName) // params.putString(FirebaseAnalytics.Param.AD_SOURCE, ad.networkName)
params.putString(FirebaseAnalytics.Param.AD_FORMAT, ad.format.getDisplayName()) // params.putString(FirebaseAnalytics.Param.AD_FORMAT, ad.format.getDisplayName())
params.putString(FirebaseAnalytics.Param.AD_UNIT_NAME, ad.adUnitId) // params.putString(FirebaseAnalytics.Param.AD_UNIT_NAME, ad.adUnitId)
params.putDouble(FirebaseAnalytics.Param.VALUE, currentImpressionRevenue) // params.putDouble(FirebaseAnalytics.Param.VALUE, currentImpressionRevenue)
params.putString(FirebaseAnalytics.Param.CURRENCY, "USD") // params.putString(FirebaseAnalytics.Param.CURRENCY, "USD")
mFirebaseAnalytics.logEvent(FirebaseAnalytics.Event.AD_IMPRESSION, params) // mFirebaseAnalytics.logEvent(FirebaseAnalytics.Event.AD_IMPRESSION, params)
mFirebaseAnalytics.logEvent("Ad_Impression_Revenue", params) // mFirebaseAnalytics.logEvent("Ad_Impression_Revenue", params)
val previousTaichiTroasCache = taichiPref.getFloat("TaichiTroasCache", 0f) // val previousTaichiTroasCache = taichiPref.getFloat("TaichiTroasCache", 0f)
val currentTaichiTroasCache = previousTaichiTroasCache + currentImpressionRevenue // val currentTaichiTroasCache = previousTaichiTroasCache + currentImpressionRevenue
if (currentTaichiTroasCache >= 0.01) { // if (currentTaichiTroasCache >= 0.01) {
val roasbundle = Bundle() // val roasbundle = Bundle()
roasbundle.putDouble(FirebaseAnalytics.Param.VALUE, currentTaichiTroasCache) // roasbundle.putDouble(FirebaseAnalytics.Param.VALUE, currentTaichiTroasCache)
roasbundle.putString(FirebaseAnalytics.Param.CURRENCY, "USD")///(Required)tROAS事件必须 // roasbundle.putString(FirebaseAnalytics.Param.CURRENCY, "USD")///(Required)tROAS事件必须
mFirebaseAnalytics.logEvent("Total_Ads_Revenue_001", roasbundle) // 给Taichi用 // mFirebaseAnalytics.logEvent("Total_Ads_Revenue_001", roasbundle) // 给Taichi用
taichiSharedPreferencesEditor.putFloat("TaichiTroasCache", 0f)//重新清零,开始计算 // taichiSharedPreferencesEditor.putFloat("TaichiTroasCache", 0f)//重新清零,开始计算
//
val logger = AppEventsLogger.newLogger(MyApplication.appContext) // val logger = AppEventsLogger.newLogger(MyApplication.appContext)
val parameters = Bundle() // val parameters = Bundle()
parameters.putString(AppEventsConstants.EVENT_PARAM_CURRENCY, "USD") // parameters.putString(AppEventsConstants.EVENT_PARAM_CURRENCY, "USD")
logger.logEvent("ad_value", currentTaichiTroasCache, parameters) // logger.logEvent("ad_value", currentTaichiTroasCache, parameters)
} else { // } else {
taichiSharedPreferencesEditor.putFloat( // taichiSharedPreferencesEditor.putFloat(
"TaichiTroasCache", // "TaichiTroasCache",
currentTaichiTroasCache.toFloat() // currentTaichiTroasCache.toFloat()
) // )
taichiSharedPreferencesEditor.commit() // taichiSharedPreferencesEditor.commit()
} // }
val obj = JSONObject() // val obj = JSONObject()
val revenue = ad.revenue // val revenue = ad.revenue
val countryCode = // val countryCode =
AppLovinSdk.getInstance(MyApplication.appContext).configuration.countryCode // AppLovinSdk.getInstance(MyApplication.appContext).configuration.countryCode
val networkName = ad.networkName // val networkName = ad.networkName
val adUnitId = ad.adUnitId // val adUnitId = ad.adUnitId
val adFormat = ad.format // val adFormat = ad.format
val placement = ad.placement // val placement = ad.placement
val networkPlacement = ad.networkPlacement // val networkPlacement = ad.networkPlacement
obj.put("valueMicros", revenue) // obj.put("valueMicros", revenue)
obj.put("currencyCode", countryCode) // obj.put("currencyCode", countryCode)
obj.put("adUnitId", adUnitId) // obj.put("adUnitId", adUnitId)
obj.put("networkName", networkName) // obj.put("networkName", networkName)
obj.put("adFormat", adFormat) // obj.put("adFormat", adFormat)
obj.put("placement", placement) // obj.put("placement", placement)
obj.put("networkPlacement", networkPlacement) // obj.put("networkPlacement", networkPlacement)
EventUtils.event("ad_price", ext = obj) // EventUtils.event("ad_price", ext = obj)
} // }
} // }
//
} //}
\ No newline at end of file \ No newline at end of file
package com.dumpster.cleaner.business.ads.applovin //package com.dumpster.cleaner.business.ads.applovin
//
import android.app.Activity //import android.app.Activity
import com.applovin.mediation.MaxAd //import com.applovin.mediation.MaxAd
import com.applovin.mediation.MaxAdListener //import com.applovin.mediation.MaxAdListener
import com.applovin.mediation.MaxError //import com.applovin.mediation.MaxError
import com.applovin.mediation.ads.MaxInterstitialAd //import com.applovin.mediation.ads.MaxInterstitialAd
import com.dumpster.cleaner.GlobalConfig //import com.dumpster.cleaner.GlobalConfig
import com.dumpster.cleaner.business.ads.AdCountDownDialog.showAdCountDownDialog //import com.dumpster.cleaner.business.ads.AdCountDownDialog.showAdCountDownDialog
import com.dumpster.cleaner.business.ads.AdEvent //import com.dumpster.cleaner.business.ads.AdEvent
import com.dumpster.cleaner.business.ads.AdState //import com.dumpster.cleaner.business.ads.AdState
import com.dumpster.cleaner.business.ads.AdsShowCallBack //import com.dumpster.cleaner.business.ads.AdsShowCallBack
import com.dumpster.cleaner.business.ads.AdsType //import com.dumpster.cleaner.business.ads.AdsType
import com.dumpster.cleaner.business.ads.LimitUtils //import com.dumpster.cleaner.business.ads.LimitUtils
//
/** ///**
*插屏广告加载显示管理类 // *插屏广告加载显示管理类
*/ // */
class MaxInsertMgr { //class MaxInsertMgr {
//
private var adState = AdState<MaxInterstitialAd>() // private var adState = AdState<MaxInterstitialAd>()
private var showCallBack: AdsShowCallBack? = null // private var showCallBack: AdsShowCallBack? = null
//
fun show( // fun show(
activity: Activity, // activity: Activity,
isUnLimit: Boolean, // isUnLimit: Boolean,
adEvent: AdEvent, // adEvent: AdEvent,
showCallBack: AdsShowCallBack? // showCallBack: AdsShowCallBack?
) { // ) {
//
if (activity.isFinishing || activity.isDestroyed) { // if (activity.isFinishing || activity.isDestroyed) {
showCallBack?.failed(1) // showCallBack?.failed(1)
return // return
} // }
//
if (showCallBack != null) { // if (showCallBack != null) {
this.showCallBack = showCallBack // this.showCallBack = showCallBack
if (adState.adDialog == null) { // if (adState.adDialog == null) {
adState.adDialog = activity.showAdCountDownDialog() // adState.adDialog = activity.showAdCountDownDialog()
} // }
adEvent.adPrepareShow() // adEvent.adPrepareShow()
} // }
//
if (!adState.loadingAd) { // if (!adState.loadingAd) {
if (!isUnLimit) { // if (!isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.INSERT, adEvent)) { // if (!LimitUtils.isAdShow(AdsType.INSERT, adEvent)) {
showCallBack?.failed(3) // showCallBack?.failed(3)
return // return
} // }
if (LimitUtils.isIntervalLimited(adEvent)) { // if (LimitUtils.isIntervalLimited(adEvent)) {
showCallBack?.failed(4) // showCallBack?.failed(4)
return // return
} // }
} // }
//
if (!adAvailable() || adState.currentAd == null) { // if (!adAvailable() || adState.currentAd == null) {
loadAd(activity, adEvent, isUnLimit) // loadAd(activity, adEvent, isUnLimit)
return // return
} // }
//
if (adState.currentAd?.isReady == false) { // if (adState.currentAd?.isReady == false) {
loadAd(activity, adEvent, isUnLimit) // loadAd(activity, adEvent, isUnLimit)
return // return
} // }
showReadyAd(adEvent) // showReadyAd(adEvent)
} // }
//
} // }
//
//
private fun showReadyAd(adEvent: AdEvent) { // private fun showReadyAd(adEvent: AdEvent) {
adState.currentAd?.run { // adState.currentAd?.run {
setListener(object : MaxAdListener { // setListener(object : MaxAdListener {
override fun onAdLoaded(p0: MaxAd) = Unit // override fun onAdLoaded(p0: MaxAd) = Unit
override fun onAdLoadFailed(p0: String, p1: MaxError) = Unit // override fun onAdLoadFailed(p0: String, p1: MaxError) = Unit
//
override fun onAdDisplayed(ad: MaxAd) { // override fun onAdDisplayed(ad: MaxAd) {
//
adState.onAdDisplayed() // adState.onAdDisplayed()
showCallBack?.show() // showCallBack?.show()
//
(adEvent as AdMaxEvent).showAd(ad, activity::class.simpleName) // (adEvent as AdMaxEvent).showAd(ad, activity::class.simpleName)
//计数 // //计数
LimitUtils.addDisplayNum() // LimitUtils.addDisplayNum()
} // }
//
override fun onAdDisplayFailed(ad: MaxAd, error: MaxError) { // override fun onAdDisplayFailed(ad: MaxAd, error: MaxError) {
adState.onAdDisplayFailed() // adState.onAdDisplayFailed()
showCallBack?.adFailed() // showCallBack?.adFailed()
showCallBack = null // showCallBack = null
//
(adEvent as AdMaxEvent).adShowError(error) // (adEvent as AdMaxEvent).adShowError(error)
} // }
//
override fun onAdHidden(p0: MaxAd) { // override fun onAdHidden(p0: MaxAd) {
//
adState.onAdHidden() // adState.onAdHidden()
showCallBack?.close() // showCallBack?.close()
//
loadAd(activity, AdMaxEvent("interAd", "preload")) // loadAd(activity, AdMaxEvent("interAd", "preload"))
} // }
//
override fun onAdClicked(ad: MaxAd) { // override fun onAdClicked(ad: MaxAd) {
(adEvent as AdMaxEvent).clickAd(ad) // (adEvent as AdMaxEvent).clickAd(ad)
//计数 // //计数
LimitUtils.addClickNum() // LimitUtils.addClickNum()
} // }
//
//
}) // })
setRevenueListener(AdMaxEvent.EventOnPaidEventListener()) // setRevenueListener(AdMaxEvent.EventOnPaidEventListener())
//
showAd(activity) // showAd(activity)
} // }
} // }
//
//
fun loadAd( // fun loadAd(
ac: Activity, // ac: Activity,
adEvent: AdEvent, // adEvent: AdEvent,
isUnLimit: Boolean = false, // isUnLimit: Boolean = false,
) { // ) {
if (!isUnLimit) { // if (!isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.INSERT, adEvent)) { // if (!LimitUtils.isAdShow(AdsType.INSERT, adEvent)) {
this.showCallBack?.close(4) // this.showCallBack?.close(4)
this.showCallBack = null // this.showCallBack = null
return // return
} // }
} // }
//
if (!adState.loadingAd) { // if (!adState.loadingAd) {
adState.loadingAd = true // adState.loadingAd = true
//
adEvent.adPulStart() // adEvent.adPulStart()
//
adState.currentAd = MaxInterstitialAd(GlobalConfig.ID_MAX_INTER, ac) // adState.currentAd = MaxInterstitialAd(GlobalConfig.ID_MAX_INTER, ac)
adState.currentAd?.setListener(object : MaxAdListener { // adState.currentAd?.setListener(object : MaxAdListener {
//
override fun onAdDisplayed(p0: MaxAd) = Unit // override fun onAdDisplayed(p0: MaxAd) = Unit
override fun onAdHidden(p0: MaxAd) = Unit // override fun onAdHidden(p0: MaxAd) = Unit
override fun onAdClicked(p0: MaxAd) = Unit // override fun onAdClicked(p0: MaxAd) = Unit
override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) = Unit // override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) = Unit
//
override fun onAdLoaded(ad: MaxAd) { // override fun onAdLoaded(ad: MaxAd) {
adState.onAdLoaded(null, adEvent) // adState.onAdLoaded(null, adEvent)
//
show(ac, isUnLimit, adEvent, null) // show(ac, isUnLimit, adEvent, null)
//
(adEvent as AdMaxEvent).pullAd(ad) // (adEvent as AdMaxEvent).pullAd(ad)
LimitUtils.addRequestNum() // LimitUtils.addRequestNum()
} // }
//
override fun onAdLoadFailed(ad: String, error: MaxError) { // override fun onAdLoadFailed(ad: String, error: MaxError) {
adState.onAdLoadFailed() // adState.onAdLoadFailed()
//
(adEvent as AdMaxEvent).pullAd(null, error) // (adEvent as AdMaxEvent).pullAd(null, error)
//
showCallBack?.adFailed(5) // showCallBack?.adFailed(5)
showCallBack = null // showCallBack = null
} // }
//
}) // })
adState.currentAd?.loadAd() // adState.currentAd?.loadAd()
} // }
} // }
//
//
private fun adAvailable() = ((System.currentTimeMillis() - adState.lastLoadTime) / 1000 / 60).toInt() < 30 // private fun adAvailable() = ((System.currentTimeMillis() - adState.lastLoadTime) / 1000 / 60).toInt() < 30
} //}
\ No newline at end of file \ No newline at end of file
package com.dumpster.cleaner.business.ads.applovin //package com.dumpster.cleaner.business.ads.applovin
//
import androidx.annotation.LayoutRes //import androidx.annotation.LayoutRes
import com.applovin.mediation.MaxAd //import com.applovin.mediation.MaxAd
import com.applovin.mediation.MaxError //import com.applovin.mediation.MaxError
import com.applovin.mediation.nativeAds.MaxNativeAdListener //import com.applovin.mediation.nativeAds.MaxNativeAdListener
import com.applovin.mediation.nativeAds.MaxNativeAdLoader //import com.applovin.mediation.nativeAds.MaxNativeAdLoader
import com.applovin.mediation.nativeAds.MaxNativeAdView //import com.applovin.mediation.nativeAds.MaxNativeAdView
import com.dumpster.cleaner.GlobalConfig //import com.dumpster.cleaner.GlobalConfig
import com.dumpster.cleaner.business.ads.AdsType //import com.dumpster.cleaner.business.ads.AdsType
import com.dumpster.cleaner.business.ads.LimitUtils //import com.dumpster.cleaner.business.ads.LimitUtils
import com.dumpster.cleaner.business.ads.NativeParentView //import com.dumpster.cleaner.business.ads.NativeParentView
import com.dumpster.cleaner.business.helper.EventUtils //import com.dumpster.cleaner.business.helper.EventUtils
import org.json.JSONObject //import org.json.JSONObject
import java.util.UUID //import java.util.UUID
//
/** ///**
*原生广告加载显示管理类 // *原生广告加载显示管理类
*/ // */
class MaxNativeMgr { //class MaxNativeMgr {
//
/** // /**
* 上一次的缓存成功时间 // * 上一次的缓存成功时间
*/ // */
protected var lastTime: Long = 0 // protected var lastTime: Long = 0
//
/** // /**
* 原生广告 // * 原生广告
*/ // */
private var currentAd: MaxAd? = null // private var currentAd: MaxAd? = null
private var currentLoader: MaxNativeAdLoader? = null // private var currentLoader: MaxNativeAdLoader? = null
//
//
private fun loadAd( // private fun loadAd(
adMaxEvent: AdMaxEvent, // adMaxEvent: AdMaxEvent,
parent: NativeParentView, // parent: NativeParentView,
@LayoutRes layout: Int // @LayoutRes layout: Int
) { // ) {
//
if (!LimitUtils.isAdShow(AdsType.NATIVE, adMaxEvent)) return // if (!LimitUtils.isAdShow(AdsType.NATIVE, adMaxEvent)) return
//
val reqId = UUID.randomUUID().toString() // val reqId = UUID.randomUUID().toString()
val obj = JSONObject() // val obj = JSONObject()
obj.put("req_id", reqId) // obj.put("req_id", reqId)
obj.put("ad_type", "nativeAd") // obj.put("ad_type", "nativeAd")
//
val nativeAdLoader = MaxNativeAdLoader(GlobalConfig.ID_MAX_NATIVE, parent.context) // val nativeAdLoader = MaxNativeAdLoader(GlobalConfig.ID_MAX_NATIVE, parent.context)
//
nativeAdLoader.setNativeAdListener(object : MaxNativeAdListener() { // nativeAdLoader.setNativeAdListener(object : MaxNativeAdListener() {
//
override fun onNativeAdLoaded(nativeAdView: MaxNativeAdView?, ad: MaxAd) { // override fun onNativeAdLoaded(nativeAdView: MaxNativeAdView?, ad: MaxAd) {
currentLoader = nativeAdLoader // currentLoader = nativeAdLoader
currentAd = ad // currentAd = ad
lastTime = System.currentTimeMillis() // lastTime = System.currentTimeMillis()
adMaxEvent.pullAd(ad) // adMaxEvent.pullAd(ad)
nativeAdLoader.setRevenueListener(AdMaxEvent.EventOnPaidEventListener()) // nativeAdLoader.setRevenueListener(AdMaxEvent.EventOnPaidEventListener())
show(adMaxEvent, parent, layout) // show(adMaxEvent, parent, layout)
} // }
//
override fun onNativeAdLoadFailed(adUnitId: String, error: MaxError) { // override fun onNativeAdLoadFailed(adUnitId: String, error: MaxError) {
adMaxEvent.pullAd(null, error) // adMaxEvent.pullAd(null, error)
} // }
//
override fun onNativeAdClicked(ad: MaxAd) { // override fun onNativeAdClicked(ad: MaxAd) {
//
} // }
//
}) // })
nativeAdLoader.loadAd() // nativeAdLoader.loadAd()
} // }
//
fun show( // fun show(
adMaxEvent: AdMaxEvent, // adMaxEvent: AdMaxEvent,
parent: NativeParentView, // parent: NativeParentView,
@LayoutRes layout: Int, // @LayoutRes layout: Int,
nativeCallBack: ((Any?) -> Unit)? = null // nativeCallBack: ((Any?) -> Unit)? = null
) { // ) {
if (!LimitUtils.isAdShow(AdsType.NATIVE, adMaxEvent)) { // if (!LimitUtils.isAdShow(AdsType.NATIVE, adMaxEvent)) {
currentLoader = null // currentLoader = null
currentAd = null // currentAd = null
return // return
} // }
val nativeAd = currentAd // val nativeAd = currentAd
val nativeLoader = currentLoader // val nativeLoader = currentLoader
if ((nativeAd == null || nativeLoader == null).also { // if ((nativeAd == null || nativeLoader == null).also {
if (it) { // if (it) {
val obj2 = JSONObject() // val obj2 = JSONObject()
obj2.put("reason", "no_ad") // obj2.put("reason", "no_ad")
obj2.put("ad_unit", "nativeAd") // obj2.put("ad_unit", "nativeAd")
EventUtils.event("ad_show_error", ext = obj2) // EventUtils.event("ad_show_error", ext = obj2)
} // }
} || (!adAvailable()).also { // } || (!adAvailable()).also {
if (it) { // if (it) {
val obj2 = JSONObject() // val obj2 = JSONObject()
obj2.put("ad_unit", "nativeAd") // obj2.put("ad_unit", "nativeAd")
EventUtils.event("ad_expire", ext = obj2) // EventUtils.event("ad_expire", ext = obj2)
} // }
}) { // }) {
//缓存过期了就清空 // //缓存过期了就清空
currentLoader = null // currentLoader = null
currentAd = null // currentAd = null
loadAd(AdMaxEvent("nativeAd", "preload"), parent, layout) // loadAd(AdMaxEvent("nativeAd", "preload"), parent, layout)
return // return
} // }
val obj = JSONObject() // val obj = JSONObject()
obj.put("ad_unit", "nativeAd") // obj.put("ad_unit", "nativeAd")
EventUtils.event("ad_prepare_show", ext = obj) // EventUtils.event("ad_prepare_show", ext = obj)
parent.setNativeAd(nativeLoader!!, nativeAd!!, layout) // parent.setNativeAd(nativeLoader!!, nativeAd!!, layout)
nativeCallBack?.invoke(nativeAd) // nativeCallBack?.invoke(nativeAd)
} // }
//
private fun adAvailable(): Boolean { // private fun adAvailable(): Boolean {
return ((System.currentTimeMillis() - lastTime) / 1000 / 60).toInt() < 30 // return ((System.currentTimeMillis() - lastTime) / 1000 / 60).toInt() < 30
} // }
} //}
\ No newline at end of file \ No newline at end of file
package com.dumpster.cleaner.business.ads.applovin //package com.dumpster.cleaner.business.ads.applovin
//
import android.app.Activity //import android.app.Activity
import android.content.Context //import android.content.Context
import com.applovin.mediation.MaxAd //import com.applovin.mediation.MaxAd
import com.applovin.mediation.MaxAdListener //import com.applovin.mediation.MaxAdListener
import com.applovin.mediation.MaxError //import com.applovin.mediation.MaxError
import com.applovin.mediation.ads.MaxAppOpenAd //import com.applovin.mediation.ads.MaxAppOpenAd
import com.dumpster.cleaner.GlobalConfig //import com.dumpster.cleaner.GlobalConfig
import com.dumpster.cleaner.business.ads.AdEvent //import com.dumpster.cleaner.business.ads.AdEvent
import com.dumpster.cleaner.business.ads.AdState //import com.dumpster.cleaner.business.ads.AdState
import com.dumpster.cleaner.business.ads.AdsShowCallBack //import com.dumpster.cleaner.business.ads.AdsShowCallBack
import com.dumpster.cleaner.business.ads.AdsType //import com.dumpster.cleaner.business.ads.AdsType
import com.dumpster.cleaner.business.ads.LimitUtils //import com.dumpster.cleaner.business.ads.LimitUtils
//
/** ///**
* 开屏广告加载显示管理类 // * 开屏广告加载显示管理类
*/ // */
class MaxOpenMgr { //class MaxOpenMgr {
//
private val adState = AdState<MaxAppOpenAd>() // private val adState = AdState<MaxAppOpenAd>()
private var showCallBack: AdsShowCallBack? = null // private var showCallBack: AdsShowCallBack? = null
//
fun show(activity: Activity, isUnLimit: Boolean, adEvent: AdEvent, showCallBack: AdsShowCallBack?) { // fun show(activity: Activity, isUnLimit: Boolean, adEvent: AdEvent, showCallBack: AdsShowCallBack?) {
if (activity.isFinishing || activity.isDestroyed) { // if (activity.isFinishing || activity.isDestroyed) {
return // return
} // }
//
if (showCallBack != null) { // if (showCallBack != null) {
this.showCallBack = showCallBack // this.showCallBack = showCallBack
adEvent.adPrepareShow() // adEvent.adPrepareShow()
} // }
//
if (!adState.loadingAd) { // if (!adState.loadingAd) {
//
if (!isUnLimit) { // if (!isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.OPEN, adEvent)) { // if (!LimitUtils.isAdShow(AdsType.OPEN, adEvent)) {
showCallBack?.failed() // showCallBack?.failed()
return // return
} // }
if (LimitUtils.isIntervalLimited(adEvent)) { // if (LimitUtils.isIntervalLimited(adEvent)) {
showCallBack?.failed() // showCallBack?.failed()
return // return
} // }
} // }
//
if (!adAvailable() || adState.currentAd == null) { // if (!adAvailable() || adState.currentAd == null) {
loadAd(activity, isUnLimit, adEvent) // loadAd(activity, isUnLimit, adEvent)
return // return
} // }
//
if (adState.currentAd?.isReady != true) { // if (adState.currentAd?.isReady != true) {
loadAd(activity, isUnLimit, adEvent) // loadAd(activity, isUnLimit, adEvent)
return // return
} // }
showReadyAd(activity, adEvent) // showReadyAd(activity, adEvent)
} // }
//
//
} // }
//
//
private fun showReadyAd(activity: Activity, adEvent: AdEvent) { // private fun showReadyAd(activity: Activity, adEvent: AdEvent) {
adState.currentAd?.run { // adState.currentAd?.run {
setListener(object : MaxAdListener { // setListener(object : MaxAdListener {
override fun onAdLoaded(p0: MaxAd) { // override fun onAdLoaded(p0: MaxAd) {
//
} // }
//
override fun onAdDisplayed(ad: MaxAd) { // override fun onAdDisplayed(ad: MaxAd) {
adState.onAdDisplayed() // adState.onAdDisplayed()
showCallBack?.show() // showCallBack?.show()
//
LimitUtils.addDisplayNum() // LimitUtils.addDisplayNum()
(adEvent as AdMaxEvent).showAd(ad, activity::class.simpleName) // (adEvent as AdMaxEvent).showAd(ad, activity::class.simpleName)
} // }
//
override fun onAdHidden(p0: MaxAd) { // override fun onAdHidden(p0: MaxAd) {
adState.onAdHidden() // adState.onAdHidden()
showCallBack?.close() // showCallBack?.close()
showCallBack = null // showCallBack = null
//
loadAd(activity.applicationContext, false, AdMaxEvent("openAd", "preload")) // loadAd(activity.applicationContext, false, AdMaxEvent("openAd", "preload"))
} // }
//
override fun onAdClicked(ad: MaxAd) { // override fun onAdClicked(ad: MaxAd) {
(adEvent as AdMaxEvent).clickAd(ad) // (adEvent as AdMaxEvent).clickAd(ad)
//计数 // //计数
LimitUtils.addClickNum() // LimitUtils.addClickNum()
} // }
//
override fun onAdLoadFailed(p0: String, p1: MaxError) { // override fun onAdLoadFailed(p0: String, p1: MaxError) {
//
} // }
//
override fun onAdDisplayFailed(p0: MaxAd, error: MaxError) { // override fun onAdDisplayFailed(p0: MaxAd, error: MaxError) {
adState.onAdDisplayFailed() // adState.onAdDisplayFailed()
showCallBack?.adFailed() // showCallBack?.adFailed()
showCallBack = null // showCallBack = null
adEvent.adShowError(error) // adEvent.adShowError(error)
} // }
//
}) // })
//
showAd() // showAd()
} // }
} // }
//
fun loadAd(context: Context, isUnLimit: Boolean, adEvent: AdEvent) { // fun loadAd(context: Context, isUnLimit: Boolean, adEvent: AdEvent) {
//
if (!isUnLimit) { // if (!isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.OPEN, adEvent)) { // if (!LimitUtils.isAdShow(AdsType.OPEN, adEvent)) {
this.showCallBack?.close() // this.showCallBack?.close()
this.showCallBack = null // this.showCallBack = null
return // return
} // }
} // }
//
if (!adState.loadingAd) { // if (!adState.loadingAd) {
adState.loadingAd = true // adState.loadingAd = true
//
adEvent.adPulStart() // adEvent.adPulStart()
//
adState.currentAd = MaxAppOpenAd(GlobalConfig.ID_MAX_OPEN, context) // adState.currentAd = MaxAppOpenAd(GlobalConfig.ID_MAX_OPEN, context)
adState.currentAd?.setListener(object : MaxAdListener { // adState.currentAd?.setListener(object : MaxAdListener {
override fun onAdLoaded(ad: MaxAd) { // override fun onAdLoaded(ad: MaxAd) {
// adState.onAdLoaded(null) //// adState.onAdLoaded(null)
// val ac = adState.activityRef?.get() //// val ac = adState.activityRef?.get()
// if (ac != null) { //// if (ac != null) {
// show(ac, isUnLimit, adEvent, null) //// show(ac, isUnLimit, adEvent, null)
// } //// }
(adEvent as AdMaxEvent).pullAd(ad) // (adEvent as AdMaxEvent).pullAd(ad)
LimitUtils.addRequestNum() // LimitUtils.addRequestNum()
} // }
//
override fun onAdDisplayed(p0: MaxAd) { // override fun onAdDisplayed(p0: MaxAd) {
//
} // }
//
override fun onAdHidden(p0: MaxAd) { // override fun onAdHidden(p0: MaxAd) {
//
} // }
//
override fun onAdClicked(p0: MaxAd) { // override fun onAdClicked(p0: MaxAd) {
} // }
//
override fun onAdLoadFailed(p0: String, error: MaxError) { // override fun onAdLoadFailed(p0: String, error: MaxError) {
adState.onAdLoadFailed() // adState.onAdLoadFailed()
showCallBack?.adFailed() // showCallBack?.adFailed()
showCallBack = null // showCallBack = null
(adEvent as AdMaxEvent).pullAd(null, error) // (adEvent as AdMaxEvent).pullAd(null, error)
} // }
//
override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) { // override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) {
//
} // }
//
}) // })
adState.currentAd?.loadAd() // adState.currentAd?.loadAd()
} // }
} // }
//
//
fun adAvailable() = ((System.currentTimeMillis() - adState.lastLoadTime) / 1000 / 60).toInt() < 30 // fun adAvailable() = ((System.currentTimeMillis() - adState.lastLoadTime) / 1000 / 60).toInt() < 30
} //}
\ No newline at end of file \ No newline at end of file
...@@ -17,6 +17,7 @@ import com.dumpster.cleaner.base.cleanFileBeans ...@@ -17,6 +17,7 @@ import com.dumpster.cleaner.base.cleanFileBeans
import com.dumpster.cleaner.bean.FeatureBean.Companion.JUNK_CLEAN import com.dumpster.cleaner.bean.FeatureBean.Companion.JUNK_CLEAN
import com.dumpster.cleaner.bean.FileBean import com.dumpster.cleaner.bean.FileBean
import com.dumpster.cleaner.business.ads.AdsMgr 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.ActivityJunkCleanBinding
import com.dumpster.cleaner.databinding.ItemJunkCleanChildBinding import com.dumpster.cleaner.databinding.ItemJunkCleanChildBinding
import com.dumpster.cleaner.databinding.ItemJunkCleanGroupBinding import com.dumpster.cleaner.databinding.ItemJunkCleanGroupBinding
...@@ -133,6 +134,11 @@ class JunkCleanActivity : BaseActivity<ActivityJunkCleanBinding>(ActivityJunkCle ...@@ -133,6 +134,11 @@ class JunkCleanActivity : BaseActivity<ActivityJunkCleanBinding>(ActivityJunkCle
selectedFiles = list.flatMap { it.items.takeIf { it.isNotEmpty() }?.filter { it.isSelected } ?: emptyList() } selectedFiles = list.flatMap { it.items.takeIf { it.isNotEmpty() }?.filter { it.isSelected } ?: emptyList() }
total = selectedFiles.sumOf { it.length } total = selectedFiles.sumOf { it.length }
setClean() 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 ...@@ -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.business.service.StayJobService.Companion.startStayJobService
import com.dumpster.cleaner.databinding.ActivitySplashBinding import com.dumpster.cleaner.databinding.ActivitySplashBinding
import com.dumpster.cleaner.ui.dialog.StoragePermissionDialog 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.ui.main.MainActivity
import com.dumpster.cleaner.utils.LogEx import com.dumpster.cleaner.utils.LogEx
import com.dumpster.cleaner.utils.PermissionUtils.checkStorePermission import com.dumpster.cleaner.utils.PermissionUtils.checkStorePermission
...@@ -84,6 +84,9 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>(ActivitySplashBinding ...@@ -84,6 +84,9 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>(ActivitySplashBinding
requestNotificationPermission() requestNotificationPermission()
showLoadingAd() showLoadingAd()
setPrivacyPolicy() setPrivacyPolicy()
viewModel.jumpNext={
actionIdJump()
}
} }
private fun setPrivacyPolicy() { private fun setPrivacyPolicy() {
...@@ -235,7 +238,7 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>(ActivitySplashBinding ...@@ -235,7 +238,7 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>(ActivitySplashBinding
when { when {
!isGuided -> { !isGuided -> {
isGuided = true isGuided = true
goToAc(GuideCleanActivity::class.java) goToAc(CleanGuideActivity::class.java)
finish() 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
{
"v": "5.7.6",
"fr": 8,
"ip": 0,
"op": 48,
"w": 1080,
"h": 1146,
"nm": "首次扫描",
"ddd": 0,
"assets": [
{
"id": "image_0",
"w": 798,
"h": 1068,
"u": "",
"p": "data:image/png;base64,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",
"e": 1
},
{
"id": "image_1",
"w": 780,
"h": 174,
"u": "",
"p": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAwwAAACuBAMAAABpbZcwAAAAJHpUWHRDcmVhdG9yAAAImXNMyU9KVXBMK0ktUnBNS0tNLikGAEF6Bs5qehXFAAAACXBIWXMAAAABAAAAAQBPJcTWAAAAHlBMVEX5+fn+/v7///////////////////////////////8kXXVtAAAACXRSTlMFEU01QSkdWWR1eI/OAAAEY0lEQVR42u2VzY2rShCFazIwGweAkAgAk4BNBgjvZ2EC8MbOwDeFl+2r6m5+Zqyr93THplpX30d1URxgFn3mYPkHMkDYAmwAbMAGwAZsAGzABsAGbABswAbABmwAbMAGwIa/woZfkAHYgA2ADdgA2IANgA3YANiADfA/ucsd/NE0PDi8j8cjpOHxi+W59LeBL0IOyAMyQG53Dv9D03C/sbyXpeFxu+nMclyi62ZGsPzW/SbWWN5LpjCAJ8IWYANgAzbAkw319VZzOB9S39gF/0Ou15tWTXftmoa6Dh8mumPXNBg61/V1nukbd6kDpe1/Pc/0jXuyAXyRa/RjatcYi5K+aRddZV3qWJc6GaZc6Zt2KaMn6zTUUYsRYd5i1jSEFISqyxiK6NCVebNZQiqiXKdv0gLzNrPaUH65Va8m5s1meTKG/1KHWUrIAGzABsCGzGw4lseqtM7hdwgu5HDENFTmxXxUK4V5i7kSm8J8nJddxyeZt5h1EnWh00ENABfC5ss0wNasvZDjsesqFbuqCjft3MV7X1X01+rHbmWJqFKGm3H/06s2denFoMZr9FfpK9WaxMmsiT7YdXpWz116en4+PY3+Q92uVlbJMQnhodm1eQr65OryHvoP9bTjyZ1KuuDNsUtm2bK5i3q36PpGuhtP6D/RVztuTcKd+X41v1fNf6OaHkhTFWOD/ud6+uLPT1TSrYyCbTg+XQoG5ICwBdgA2IAN8N2G06k7UN5laThRznXQNGg/UK6lHyXLxIlyrZiGRi0BT0RX0zUncMVsOJCGHNKgPhwsDwe6Uz9J0zRhbtQKuk9v4m/DiTS4pyF6cOC/0q1rk5iKJikn+ubdfpmlgQzABmwAbMAGwIY8bWjbtumt7Kxw9jhbGvrGjAjnhrPLWdPQmCFNNKbl7HKW8EXSC3OCY/tDU6AnCZ6YLUMLDoQ49NInhqYHL1rppxSQBhds/4de4hTMiOd+iEc7N/R36WnfNQ2zuNS0liv0d+nBDE3DNwvSjXaR4uPor9dnrR9k+Eo76FtDaqsB/T16Er9/lNIDfXgh2BZdQ3+13g/L1j+lYeUQ+pv1lfJ7G+CttF+usCELsAEbABvysuE8XCiH0nVZLmW4DL+pM/qr9fMwzHWxPt21NKg16z7EIby3XKK/Qk+T5cDUedvlconhiOdzms7zhP4qPbiQBD0vm65nWb0Ebsh4Bn+ELcjChst4ptxL2IQcSs7jSLmX/USHGqeB2WGWMXEZF5i3nmWEDBD+J3OYSUNOaQBsAGzIxIZP8Ic0ZMGeNOQQhk/Z7z/HfWzTWl2iv1WfJ9lDBvBRygLSkEca9sUn5V7CJmRQhYRO+ZamoQjjnu7Xi0KiH2GmO/V9EdJQpEjQPfo+pgH8wQZsAGzABniyYbcrPsCZnabhg39GZ3aahmIHzhQ7sf5B+daH8GHOAeGTkAOkIZs0aKN8S0TYhAxK7MMklH/ZDwTlWZGdAED8iU4T5VUAAAAAAAD/yb9pEzMqJ0sOtAAAAABJRU5ErkJggg==",
"e": 1
},
{
"id": "image_2",
"w": 528,
"h": 918,
"u": "",
"p": "data:image/png;base64,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",
"e": 1
}
],
"layers": [
{
"ddd": 0,
"ind": 1,
"ty": 2,
"nm": "矩形 4077@3x.png",
"cl": "png",
"refId": "image_0",
"sr": 1,
"ks": {
"o": {
"a": 0,
"k": 100,
"ix": 11
},
"r": {
"a": 0,
"k": 0,
"ix": 10
},
"p": {
"a": 0,
"k": [
540,
573,
0
],
"ix": 2,
"l": 2
},
"a": {
"a": 0,
"k": [
399,
534,
0
],
"ix": 1,
"l": 2
},
"s": {
"a": 0,
"k": [
100,
100,
100
],
"ix": 6,
"l": 2
}
},
"ao": 0,
"ip": 0,
"op": 50,
"st": 0,
"bm": 0
},
{
"ddd": 0,
"ind": 2,
"ty": 2,
"nm": "组 4141@3x.png",
"cl": "png",
"refId": "image_1",
"sr": 1,
"ks": {
"o": {
"a": 0,
"k": 100,
"ix": 11
},
"r": {
"a": 0,
"k": 0,
"ix": 10
},
"p": {
"a": 1,
"k": [
{
"i": {
"x": 0.833,
"y": 0.833
},
"o": {
"x": 0.167,
"y": 0.167
},
"t": 0,
"s": [
540,
209,
0
],
"e": [
540,
1011,
0
],
"to": [
0,
0,
0
],
"ti": [
0,
0,
0
]
},
{
"i": {
"x": 0.833,
"y": 0.833
},
"o": {
"x": 0.167,
"y": 0.167
},
"t": 8,
"s": [
540,
1011,
0
],
"e": [
540,
209,
0
],
"to": [
0,
0,
0
],
"ti": [
0,
0,
0
]
},
{
"i": {
"x": 0.833,
"y": 0.833
},
"o": {
"x": 0.167,
"y": 0.167
},
"t": 16,
"s": [
540,
209,
0
],
"e": [
540,
1011,
0
],
"to": [
0,
0,
0
],
"ti": [
0,
0,
0
]
},
{
"i": {
"x": 0.833,
"y": 0.833
},
"o": {
"x": 0.167,
"y": 0.167
},
"t": 24,
"s": [
540,
1011,
0
],
"e": [
540,
209,
0
],
"to": [
0,
0,
0
],
"ti": [
0,
0,
0
]
},
{
"i": {
"x": 0.833,
"y": 0.833
},
"o": {
"x": 0.167,
"y": 0.167
},
"t": 32,
"s": [
540,
209,
0
],
"e": [
540,
1011,
0
],
"to": [
0,
0,
0
],
"ti": [
0,
0,
0
]
},
{
"i": {
"x": 0.833,
"y": 0.833
},
"o": {
"x": 0.167,
"y": 0.167
},
"t": 40,
"s": [
540,
1011,
0
],
"e": [
540,
209,
0
],
"to": [
0,
0,
0
],
"ti": [
0,
0,
0
]
},
{
"t": 48
}
],
"ix": 2,
"l": 2
},
"a": {
"a": 0,
"k": [
390,
87,
0
],
"ix": 1,
"l": 2
},
"s": {
"a": 0,
"k": [
100,
100,
100
],
"ix": 6,
"l": 2
}
},
"ao": 0,
"ip": 0,
"op": 50,
"st": 0,
"bm": 0
},
{
"ddd": 0,
"ind": 4,
"ty": 2,
"nm": "组 4160@3x.png",
"cl": "png",
"refId": "image_2",
"sr": 1,
"ks": {
"o": {
"a": 0,
"k": 100,
"ix": 11
},
"r": {
"a": 0,
"k": 0,
"ix": 10
},
"p": {
"a": 0,
"k": [
540,
583,
0
],
"ix": 2,
"l": 2
},
"a": {
"a": 0,
"k": [
264,
459,
0
],
"ix": 1,
"l": 2
},
"s": {
"a": 1,
"k": [
{
"i": {
"x": [
0.833,
0.833,
0.833
],
"y": [
0.833,
0.833,
0.833
]
},
"o": {
"x": [
0.167,
0.167,
0.167
],
"y": [
0.167,
0.167,
0.167
]
},
"t": 0,
"s": [
100,
100,
100
],
"e": [
96,
96,
100
]
},
{
"i": {
"x": [
0.833,
0.833,
0.833
],
"y": [
0.833,
0.833,
0.833
]
},
"o": {
"x": [
0.167,
0.167,
0.167
],
"y": [
0.167,
0.167,
0.167
]
},
"t": 4,
"s": [
96,
96,
100
],
"e": [
100,
100,
100
]
},
{
"i": {
"x": [
0.833,
0.833,
0.833
],
"y": [
0.833,
0.833,
0.833
]
},
"o": {
"x": [
0.167,
0.167,
0.167
],
"y": [
0.167,
0.167,
0.167
]
},
"t": 8,
"s": [
100,
100,
100
],
"e": [
96,
96,
100
]
},
{
"i": {
"x": [
0.833,
0.833,
0.833
],
"y": [
0.833,
0.833,
0.833
]
},
"o": {
"x": [
0.167,
0.167,
0.167
],
"y": [
0.167,
0.167,
0.167
]
},
"t": 12,
"s": [
96,
96,
100
],
"e": [
100,
100,
100
]
},
{
"i": {
"x": [
0.833,
0.833,
0.833
],
"y": [
0.833,
0.833,
0.833
]
},
"o": {
"x": [
0.167,
0.167,
0.167
],
"y": [
0.167,
0.167,
0.167
]
},
"t": 16,
"s": [
100,
100,
100
],
"e": [
96,
96,
100
]
},
{
"i": {
"x": [
0.833,
0.833,
0.833
],
"y": [
0.833,
0.833,
0.833
]
},
"o": {
"x": [
0.167,
0.167,
0.167
],
"y": [
0.167,
0.167,
0.167
]
},
"t": 20,
"s": [
96,
96,
100
],
"e": [
100,
100,
100
]
},
{
"i": {
"x": [
0.833,
0.833,
0.833
],
"y": [
0.833,
0.833,
0.833
]
},
"o": {
"x": [
0.167,
0.167,
0.167
],
"y": [
0.167,
0.167,
0.167
]
},
"t": 24,
"s": [
100,
100,
100
],
"e": [
96,
96,
100
]
},
{
"i": {
"x": [
0.833,
0.833,
0.833
],
"y": [
0.833,
0.833,
0.833
]
},
"o": {
"x": [
0.167,
0.167,
0.167
],
"y": [
0.167,
0.167,
0.167
]
},
"t": 28,
"s": [
96,
96,
100
],
"e": [
100,
100,
100
]
},
{
"i": {
"x": [
0.833,
0.833,
0.833
],
"y": [
0.833,
0.833,
0.833
]
},
"o": {
"x": [
0.167,
0.167,
0.167
],
"y": [
0.167,
0.167,
0.167
]
},
"t": 32,
"s": [
100,
100,
100
],
"e": [
96,
96,
100
]
},
{
"i": {
"x": [
0.833,
0.833,
0.833
],
"y": [
0.833,
0.833,
0.833
]
},
"o": {
"x": [
0.167,
0.167,
0.167
],
"y": [
0.167,
0.167,
0.167
]
},
"t": 36,
"s": [
96,
96,
100
],
"e": [
100,
100,
100
]
},
{
"i": {
"x": [
0.833,
0.833,
0.833
],
"y": [
0.833,
0.833,
0.833
]
},
"o": {
"x": [
0.167,
0.167,
0.167
],
"y": [
0.167,
0.167,
0.167
]
},
"t": 40,
"s": [
100,
100,
100
],
"e": [
96,
96,
100
]
},
{
"i": {
"x": [
0.833,
0.833,
0.833
],
"y": [
0.833,
0.833,
0.833
]
},
"o": {
"x": [
0.167,
0.167,
0.167
],
"y": [
0.167,
0.167,
0.167
]
},
"t": 44,
"s": [
96,
96,
100
],
"e": [
100,
100,
100
]
},
{
"t": 48
}
],
"ix": 6,
"l": 2
}
},
"ao": 0,
"ip": 0,
"op": 50,
"st": 0,
"bm": 0
}
],
"markers": []
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
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