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()
}
fun onAdHidden() {
if (adsType == INSERT) {
interLastShowTime = System.currentTimeMillis()
}
}
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) {
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 android.os.Bundle
import com.applovin.mediation.MaxAd
import com.applovin.mediation.MaxAdRevenueListener
import com.applovin.mediation.MaxError
import com.applovin.sdk.AppLovinSdk
import com.dumpster.cleaner.MyApplication
import com.dumpster.cleaner.business.ads.AdEvent
import com.dumpster.cleaner.business.ads.taichiPref
import com.dumpster.cleaner.business.ads.taichiSharedPreferencesEditor
import com.dumpster.cleaner.business.helper.EventUtils
import com.dumpster.cleaner.utils.LogEx.logDebug
import com.facebook.appevents.AppEventsConstants
import com.facebook.appevents.AppEventsLogger
import com.google.firebase.analytics.FirebaseAnalytics
import org.json.JSONObject
class AdMaxEvent : AdEvent {
override val TAG: String = "AdMaxEvent"
constructor(adUnit: String, from: String) : super() {
this.adUnit = adUnit
this.from = from
}
fun pullAd(
ad: MaxAd?,
error: MaxError? = null
) {
val obj = JSONObject()
obj.put("UnitId", ad?.adUnitId)
obj.put("ad_unit", adUnit)
obj.put(
"creativeId",
ad?.creativeId
)
obj.put("req_id", reqId)
obj.put("from", from)
obj.put("status", if (ad == null) "0" else "1")
obj.put("networkname", ad?.networkName)
obj.put("placement", ad?.placement)
obj.put("networkplacement", ad?.networkPlacement)
obj.put("latency", ad?.requestLatencyMillis)
obj.put("valueMicros", ad?.revenue)
if (error == null) {
obj.put("status", "1")
} else {
obj.put("errMsg", error)
obj.put("status", "2")
}
EventUtils.event("ad_pull", ext = obj)
logDebug(TAG, "ad_pull $obj")
}
fun clickAd(ad: MaxAd?) {
val obj = JSONObject()
obj.put("UnitId", ad?.adUnitId)
obj.put("ad_unit", adUnit)
obj.put(
"creativeId",
ad?.creativeId
)
obj.put("networkname", ad?.networkName)
obj.put("placement", ad?.placement)
obj.put("networkplacement", ad?.networkPlacement)
obj.put("latency", ad?.requestLatencyMillis)
obj.put("valueMicros", ad?.revenue)
if (!adUnit.equals("nativeAd")) {
EventUtils.event("ad_click", ext = obj)
} else {
EventUtils.event("ad_click", ext = obj)
}
}
fun showAd(ad: MaxAd?, activity: String?) {
val obj = JSONObject()
obj.put("UnitId", ad?.adUnitId)
obj.put("ad_unit", adUnit)
obj.put(
"creativeId",
ad?.creativeId
)
obj.put("networkname", ad?.networkName)
obj.put("placement", ad?.placement)
obj.put("networkplacement", ad?.networkPlacement)
obj.put("latency", ad?.requestLatencyMillis)
obj.put("valueMicros", ad?.revenue)
obj.put("from", activity)
obj.put("mediation", "applovin")
if (adUnit != "nativeAd") {
EventUtils.event("ad_show", ext = obj)
} else {
EventUtils.event("ad_show", ext = obj)
}
}
class EventOnPaidEventListener : MaxAdRevenueListener {
override fun onAdRevenuePaid(ad: MaxAd) {
val params = Bundle()
val currentImpressionRevenue: Double = ad.revenue // In USD
val mFirebaseAnalytics = FirebaseAnalytics.getInstance(MyApplication.appContext)
params.putString(FirebaseAnalytics.Param.AD_PLATFORM, "appLovin")
params.putString(FirebaseAnalytics.Param.AD_SOURCE, ad.networkName)
params.putString(FirebaseAnalytics.Param.AD_FORMAT, ad.format.getDisplayName())
params.putString(FirebaseAnalytics.Param.AD_UNIT_NAME, ad.adUnitId)
params.putDouble(FirebaseAnalytics.Param.VALUE, currentImpressionRevenue)
params.putString(FirebaseAnalytics.Param.CURRENCY, "USD")
mFirebaseAnalytics.logEvent(FirebaseAnalytics.Event.AD_IMPRESSION, params)
mFirebaseAnalytics.logEvent("Ad_Impression_Revenue", params)
val previousTaichiTroasCache = taichiPref.getFloat("TaichiTroasCache", 0f)
val currentTaichiTroasCache = previousTaichiTroasCache + currentImpressionRevenue
if (currentTaichiTroasCache >= 0.01) {
val roasbundle = Bundle()
roasbundle.putDouble(FirebaseAnalytics.Param.VALUE, currentTaichiTroasCache)
roasbundle.putString(FirebaseAnalytics.Param.CURRENCY, "USD")///(Required)tROAS事件必须
mFirebaseAnalytics.logEvent("Total_Ads_Revenue_001", roasbundle) // 给Taichi用
taichiSharedPreferencesEditor.putFloat("TaichiTroasCache", 0f)//重新清零,开始计算
val logger = AppEventsLogger.newLogger(MyApplication.appContext)
val parameters = Bundle()
parameters.putString(AppEventsConstants.EVENT_PARAM_CURRENCY, "USD")
logger.logEvent("ad_value", currentTaichiTroasCache, parameters)
} else {
taichiSharedPreferencesEditor.putFloat(
"TaichiTroasCache",
currentTaichiTroasCache.toFloat()
)
taichiSharedPreferencesEditor.commit()
}
val obj = JSONObject()
val revenue = ad.revenue
val countryCode =
AppLovinSdk.getInstance(MyApplication.appContext).configuration.countryCode
val networkName = ad.networkName
val adUnitId = ad.adUnitId
val adFormat = ad.format
val placement = ad.placement
val networkPlacement = ad.networkPlacement
obj.put("valueMicros", revenue)
obj.put("currencyCode", countryCode)
obj.put("adUnitId", adUnitId)
obj.put("networkName", networkName)
obj.put("adFormat", adFormat)
obj.put("placement", placement)
obj.put("networkPlacement", networkPlacement)
EventUtils.event("ad_price", ext = obj)
}
}
}
\ No newline at end of file
//package com.dumpster.cleaner.business.ads.applovin
//
//import android.os.Bundle
//import com.applovin.mediation.MaxAd
//import com.applovin.mediation.MaxAdRevenueListener
//import com.applovin.mediation.MaxError
//import com.applovin.sdk.AppLovinSdk
//import com.dumpster.cleaner.MyApplication
//import com.dumpster.cleaner.business.ads.AdEvent
//import com.dumpster.cleaner.business.ads.taichiPref
//import com.dumpster.cleaner.business.ads.taichiSharedPreferencesEditor
//import com.dumpster.cleaner.business.helper.EventUtils
//import com.dumpster.cleaner.utils.LogEx.logDebug
//import com.facebook.appevents.AppEventsConstants
//import com.facebook.appevents.AppEventsLogger
//import com.google.firebase.analytics.FirebaseAnalytics
//import org.json.JSONObject
//
//
//class AdMaxEvent : AdEvent {
//
// override val TAG: String = "AdMaxEvent"
//
// constructor(adUnit: String, from: String) : super() {
// this.adUnit = adUnit
// this.from = from
// }
//
// fun pullAd(
// ad: MaxAd?,
// error: MaxError? = null
// ) {
// val obj = JSONObject()
// obj.put("UnitId", ad?.adUnitId)
// obj.put("ad_unit", adUnit)
// obj.put(
// "creativeId",
// ad?.creativeId
// )
// obj.put("req_id", reqId)
// obj.put("from", from)
// obj.put("status", if (ad == null) "0" else "1")
// obj.put("networkname", ad?.networkName)
// obj.put("placement", ad?.placement)
// obj.put("networkplacement", ad?.networkPlacement)
// obj.put("latency", ad?.requestLatencyMillis)
// obj.put("valueMicros", ad?.revenue)
// if (error == null) {
// obj.put("status", "1")
// } else {
// obj.put("errMsg", error)
// obj.put("status", "2")
// }
// EventUtils.event("ad_pull", ext = obj)
// logDebug(TAG, "ad_pull $obj")
// }
//
// fun clickAd(ad: MaxAd?) {
//
// val obj = JSONObject()
// obj.put("UnitId", ad?.adUnitId)
// obj.put("ad_unit", adUnit)
// obj.put(
// "creativeId",
// ad?.creativeId
// )
// obj.put("networkname", ad?.networkName)
// obj.put("placement", ad?.placement)
// obj.put("networkplacement", ad?.networkPlacement)
// obj.put("latency", ad?.requestLatencyMillis)
// obj.put("valueMicros", ad?.revenue)
// if (!adUnit.equals("nativeAd")) {
// EventUtils.event("ad_click", ext = obj)
// } else {
// EventUtils.event("ad_click", ext = obj)
// }
//
// }
//
// fun showAd(ad: MaxAd?, activity: String?) {
// val obj = JSONObject()
// obj.put("UnitId", ad?.adUnitId)
// obj.put("ad_unit", adUnit)
// obj.put(
// "creativeId",
// ad?.creativeId
// )
// obj.put("networkname", ad?.networkName)
// obj.put("placement", ad?.placement)
// obj.put("networkplacement", ad?.networkPlacement)
// obj.put("latency", ad?.requestLatencyMillis)
// obj.put("valueMicros", ad?.revenue)
// obj.put("from", activity)
// obj.put("mediation", "applovin")
// if (adUnit != "nativeAd") {
// EventUtils.event("ad_show", ext = obj)
// } else {
// EventUtils.event("ad_show", ext = obj)
// }
//
// }
//
//
// class EventOnPaidEventListener : MaxAdRevenueListener {
// override fun onAdRevenuePaid(ad: MaxAd) {
// val params = Bundle()
// val currentImpressionRevenue: Double = ad.revenue // In USD
// val mFirebaseAnalytics = FirebaseAnalytics.getInstance(MyApplication.appContext)
// params.putString(FirebaseAnalytics.Param.AD_PLATFORM, "appLovin")
// params.putString(FirebaseAnalytics.Param.AD_SOURCE, ad.networkName)
// params.putString(FirebaseAnalytics.Param.AD_FORMAT, ad.format.getDisplayName())
// params.putString(FirebaseAnalytics.Param.AD_UNIT_NAME, ad.adUnitId)
// params.putDouble(FirebaseAnalytics.Param.VALUE, currentImpressionRevenue)
// params.putString(FirebaseAnalytics.Param.CURRENCY, "USD")
// mFirebaseAnalytics.logEvent(FirebaseAnalytics.Event.AD_IMPRESSION, params)
// mFirebaseAnalytics.logEvent("Ad_Impression_Revenue", params)
// val previousTaichiTroasCache = taichiPref.getFloat("TaichiTroasCache", 0f)
// val currentTaichiTroasCache = previousTaichiTroasCache + currentImpressionRevenue
// if (currentTaichiTroasCache >= 0.01) {
// val roasbundle = Bundle()
// roasbundle.putDouble(FirebaseAnalytics.Param.VALUE, currentTaichiTroasCache)
// roasbundle.putString(FirebaseAnalytics.Param.CURRENCY, "USD")///(Required)tROAS事件必须
// mFirebaseAnalytics.logEvent("Total_Ads_Revenue_001", roasbundle) // 给Taichi用
// taichiSharedPreferencesEditor.putFloat("TaichiTroasCache", 0f)//重新清零,开始计算
//
// val logger = AppEventsLogger.newLogger(MyApplication.appContext)
// val parameters = Bundle()
// parameters.putString(AppEventsConstants.EVENT_PARAM_CURRENCY, "USD")
// logger.logEvent("ad_value", currentTaichiTroasCache, parameters)
// } else {
// taichiSharedPreferencesEditor.putFloat(
// "TaichiTroasCache",
// currentTaichiTroasCache.toFloat()
// )
// taichiSharedPreferencesEditor.commit()
// }
// val obj = JSONObject()
// val revenue = ad.revenue
// val countryCode =
// AppLovinSdk.getInstance(MyApplication.appContext).configuration.countryCode
// val networkName = ad.networkName
// val adUnitId = ad.adUnitId
// val adFormat = ad.format
// val placement = ad.placement
// val networkPlacement = ad.networkPlacement
// obj.put("valueMicros", revenue)
// obj.put("currencyCode", countryCode)
// obj.put("adUnitId", adUnitId)
// obj.put("networkName", networkName)
// obj.put("adFormat", adFormat)
// obj.put("placement", placement)
// obj.put("networkPlacement", networkPlacement)
// EventUtils.event("ad_price", ext = obj)
// }
// }
//
//}
\ No newline at end of file
package com.dumpster.cleaner.business.ads.applovin
import android.app.Activity
import com.applovin.mediation.MaxAd
import com.applovin.mediation.MaxAdListener
import com.applovin.mediation.MaxError
import com.applovin.mediation.ads.MaxInterstitialAd
import com.dumpster.cleaner.GlobalConfig
import com.dumpster.cleaner.business.ads.AdCountDownDialog.showAdCountDownDialog
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.LimitUtils
/**
*插屏广告加载显示管理类
*/
class MaxInsertMgr {
private var adState = AdState<MaxInterstitialAd>()
private var showCallBack: AdsShowCallBack? = null
fun show(
activity: Activity,
isUnLimit: Boolean,
adEvent: AdEvent,
showCallBack: AdsShowCallBack?
) {
if (activity.isFinishing || activity.isDestroyed) {
showCallBack?.failed(1)
return
}
if (showCallBack != null) {
this.showCallBack = showCallBack
if (adState.adDialog == null) {
adState.adDialog = activity.showAdCountDownDialog()
}
adEvent.adPrepareShow()
}
if (!adState.loadingAd) {
if (!isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.INSERT, adEvent)) {
showCallBack?.failed(3)
return
}
if (LimitUtils.isIntervalLimited(adEvent)) {
showCallBack?.failed(4)
return
}
}
if (!adAvailable() || adState.currentAd == null) {
loadAd(activity, adEvent, isUnLimit)
return
}
if (adState.currentAd?.isReady == false) {
loadAd(activity, adEvent, isUnLimit)
return
}
showReadyAd(adEvent)
}
}
private fun showReadyAd(adEvent: AdEvent) {
adState.currentAd?.run {
setListener(object : MaxAdListener {
override fun onAdLoaded(p0: MaxAd) = Unit
override fun onAdLoadFailed(p0: String, p1: MaxError) = Unit
override fun onAdDisplayed(ad: MaxAd) {
adState.onAdDisplayed()
showCallBack?.show()
(adEvent as AdMaxEvent).showAd(ad, activity::class.simpleName)
//计数
LimitUtils.addDisplayNum()
}
override fun onAdDisplayFailed(ad: MaxAd, error: MaxError) {
adState.onAdDisplayFailed()
showCallBack?.adFailed()
showCallBack = null
(adEvent as AdMaxEvent).adShowError(error)
}
override fun onAdHidden(p0: MaxAd) {
adState.onAdHidden()
showCallBack?.close()
loadAd(activity, AdMaxEvent("interAd", "preload"))
}
override fun onAdClicked(ad: MaxAd) {
(adEvent as AdMaxEvent).clickAd(ad)
//计数
LimitUtils.addClickNum()
}
})
setRevenueListener(AdMaxEvent.EventOnPaidEventListener())
showAd(activity)
}
}
fun loadAd(
ac: Activity,
adEvent: AdEvent,
isUnLimit: Boolean = false,
) {
if (!isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.INSERT, adEvent)) {
this.showCallBack?.close(4)
this.showCallBack = null
return
}
}
if (!adState.loadingAd) {
adState.loadingAd = true
adEvent.adPulStart()
adState.currentAd = MaxInterstitialAd(GlobalConfig.ID_MAX_INTER, ac)
adState.currentAd?.setListener(object : MaxAdListener {
override fun onAdDisplayed(p0: MaxAd) = Unit
override fun onAdHidden(p0: MaxAd) = Unit
override fun onAdClicked(p0: MaxAd) = Unit
override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) = Unit
override fun onAdLoaded(ad: MaxAd) {
adState.onAdLoaded(null, adEvent)
show(ac, isUnLimit, adEvent, null)
(adEvent as AdMaxEvent).pullAd(ad)
LimitUtils.addRequestNum()
}
override fun onAdLoadFailed(ad: String, error: MaxError) {
adState.onAdLoadFailed()
(adEvent as AdMaxEvent).pullAd(null, error)
showCallBack?.adFailed(5)
showCallBack = null
}
})
adState.currentAd?.loadAd()
}
}
private fun adAvailable() = ((System.currentTimeMillis() - adState.lastLoadTime) / 1000 / 60).toInt() < 30
}
\ No newline at end of file
//package com.dumpster.cleaner.business.ads.applovin
//
//import android.app.Activity
//import com.applovin.mediation.MaxAd
//import com.applovin.mediation.MaxAdListener
//import com.applovin.mediation.MaxError
//import com.applovin.mediation.ads.MaxInterstitialAd
//import com.dumpster.cleaner.GlobalConfig
//import com.dumpster.cleaner.business.ads.AdCountDownDialog.showAdCountDownDialog
//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.LimitUtils
//
///**
// *插屏广告加载显示管理类
// */
//class MaxInsertMgr {
//
// private var adState = AdState<MaxInterstitialAd>()
// private var showCallBack: AdsShowCallBack? = null
//
// fun show(
// activity: Activity,
// isUnLimit: Boolean,
// adEvent: AdEvent,
// showCallBack: AdsShowCallBack?
// ) {
//
// if (activity.isFinishing || activity.isDestroyed) {
// showCallBack?.failed(1)
// return
// }
//
// if (showCallBack != null) {
// this.showCallBack = showCallBack
// if (adState.adDialog == null) {
// adState.adDialog = activity.showAdCountDownDialog()
// }
// adEvent.adPrepareShow()
// }
//
// if (!adState.loadingAd) {
// if (!isUnLimit) {
// if (!LimitUtils.isAdShow(AdsType.INSERT, adEvent)) {
// showCallBack?.failed(3)
// return
// }
// if (LimitUtils.isIntervalLimited(adEvent)) {
// showCallBack?.failed(4)
// return
// }
// }
//
// if (!adAvailable() || adState.currentAd == null) {
// loadAd(activity, adEvent, isUnLimit)
// return
// }
//
// if (adState.currentAd?.isReady == false) {
// loadAd(activity, adEvent, isUnLimit)
// return
// }
// showReadyAd(adEvent)
// }
//
// }
//
//
// private fun showReadyAd(adEvent: AdEvent) {
// adState.currentAd?.run {
// setListener(object : MaxAdListener {
// override fun onAdLoaded(p0: MaxAd) = Unit
// override fun onAdLoadFailed(p0: String, p1: MaxError) = Unit
//
// override fun onAdDisplayed(ad: MaxAd) {
//
// adState.onAdDisplayed()
// showCallBack?.show()
//
// (adEvent as AdMaxEvent).showAd(ad, activity::class.simpleName)
// //计数
// LimitUtils.addDisplayNum()
// }
//
// override fun onAdDisplayFailed(ad: MaxAd, error: MaxError) {
// adState.onAdDisplayFailed()
// showCallBack?.adFailed()
// showCallBack = null
//
// (adEvent as AdMaxEvent).adShowError(error)
// }
//
// override fun onAdHidden(p0: MaxAd) {
//
// adState.onAdHidden()
// showCallBack?.close()
//
// loadAd(activity, AdMaxEvent("interAd", "preload"))
// }
//
// override fun onAdClicked(ad: MaxAd) {
// (adEvent as AdMaxEvent).clickAd(ad)
// //计数
// LimitUtils.addClickNum()
// }
//
//
// })
// setRevenueListener(AdMaxEvent.EventOnPaidEventListener())
//
// showAd(activity)
// }
// }
//
//
// fun loadAd(
// ac: Activity,
// adEvent: AdEvent,
// isUnLimit: Boolean = false,
// ) {
// if (!isUnLimit) {
// if (!LimitUtils.isAdShow(AdsType.INSERT, adEvent)) {
// this.showCallBack?.close(4)
// this.showCallBack = null
// return
// }
// }
//
// if (!adState.loadingAd) {
// adState.loadingAd = true
//
// adEvent.adPulStart()
//
// adState.currentAd = MaxInterstitialAd(GlobalConfig.ID_MAX_INTER, ac)
// adState.currentAd?.setListener(object : MaxAdListener {
//
// override fun onAdDisplayed(p0: MaxAd) = Unit
// override fun onAdHidden(p0: MaxAd) = Unit
// override fun onAdClicked(p0: MaxAd) = Unit
// override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) = Unit
//
// override fun onAdLoaded(ad: MaxAd) {
// adState.onAdLoaded(null, adEvent)
//
// show(ac, isUnLimit, adEvent, null)
//
// (adEvent as AdMaxEvent).pullAd(ad)
// LimitUtils.addRequestNum()
// }
//
// override fun onAdLoadFailed(ad: String, error: MaxError) {
// adState.onAdLoadFailed()
//
// (adEvent as AdMaxEvent).pullAd(null, error)
//
// showCallBack?.adFailed(5)
// showCallBack = null
// }
//
// })
// adState.currentAd?.loadAd()
// }
// }
//
//
// private fun adAvailable() = ((System.currentTimeMillis() - adState.lastLoadTime) / 1000 / 60).toInt() < 30
//}
\ No newline at end of file
package com.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
package com.dumpster.cleaner.business.ads.applovin
import android.app.Activity
import android.content.Context
import com.applovin.mediation.MaxAd
import com.applovin.mediation.MaxAdListener
import com.applovin.mediation.MaxError
import com.applovin.mediation.ads.MaxAppOpenAd
import com.dumpster.cleaner.GlobalConfig
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.LimitUtils
/**
* 开屏广告加载显示管理类
*/
class MaxOpenMgr {
private val adState = AdState<MaxAppOpenAd>()
private var showCallBack: AdsShowCallBack? = null
fun show(activity: Activity, isUnLimit: Boolean, adEvent: AdEvent, showCallBack: AdsShowCallBack?) {
if (activity.isFinishing || activity.isDestroyed) {
return
}
if (showCallBack != null) {
this.showCallBack = showCallBack
adEvent.adPrepareShow()
}
if (!adState.loadingAd) {
if (!isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.OPEN, adEvent)) {
showCallBack?.failed()
return
}
if (LimitUtils.isIntervalLimited(adEvent)) {
showCallBack?.failed()
return
}
}
if (!adAvailable() || adState.currentAd == null) {
loadAd(activity, isUnLimit, adEvent)
return
}
if (adState.currentAd?.isReady != true) {
loadAd(activity, isUnLimit, adEvent)
return
}
showReadyAd(activity, adEvent)
}
}
private fun showReadyAd(activity: Activity, adEvent: AdEvent) {
adState.currentAd?.run {
setListener(object : MaxAdListener {
override fun onAdLoaded(p0: MaxAd) {
}
override fun onAdDisplayed(ad: MaxAd) {
adState.onAdDisplayed()
showCallBack?.show()
LimitUtils.addDisplayNum()
(adEvent as AdMaxEvent).showAd(ad, activity::class.simpleName)
}
override fun onAdHidden(p0: MaxAd) {
adState.onAdHidden()
showCallBack?.close()
showCallBack = null
loadAd(activity.applicationContext, false, AdMaxEvent("openAd", "preload"))
}
override fun onAdClicked(ad: MaxAd) {
(adEvent as AdMaxEvent).clickAd(ad)
//计数
LimitUtils.addClickNum()
}
override fun onAdLoadFailed(p0: String, p1: MaxError) {
}
override fun onAdDisplayFailed(p0: MaxAd, error: MaxError) {
adState.onAdDisplayFailed()
showCallBack?.adFailed()
showCallBack = null
adEvent.adShowError(error)
}
})
showAd()
}
}
fun loadAd(context: Context, isUnLimit: Boolean, adEvent: AdEvent) {
if (!isUnLimit) {
if (!LimitUtils.isAdShow(AdsType.OPEN, adEvent)) {
this.showCallBack?.close()
this.showCallBack = null
return
}
}
if (!adState.loadingAd) {
adState.loadingAd = true
adEvent.adPulStart()
adState.currentAd = MaxAppOpenAd(GlobalConfig.ID_MAX_OPEN, context)
adState.currentAd?.setListener(object : MaxAdListener {
override fun onAdLoaded(ad: MaxAd) {
// adState.onAdLoaded(null)
// val ac = adState.activityRef?.get()
// if (ac != null) {
// show(ac, isUnLimit, adEvent, null)
// }
(adEvent as AdMaxEvent).pullAd(ad)
LimitUtils.addRequestNum()
}
override fun onAdDisplayed(p0: MaxAd) {
}
override fun onAdHidden(p0: MaxAd) {
}
override fun onAdClicked(p0: MaxAd) {
}
override fun onAdLoadFailed(p0: String, error: MaxError) {
adState.onAdLoadFailed()
showCallBack?.adFailed()
showCallBack = null
(adEvent as AdMaxEvent).pullAd(null, error)
}
override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) {
}
})
adState.currentAd?.loadAd()
}
}
fun adAvailable() = ((System.currentTimeMillis() - adState.lastLoadTime) / 1000 / 60).toInt() < 30
}
\ No newline at end of file
//package com.dumpster.cleaner.business.ads.applovin
//
//import android.app.Activity
//import android.content.Context
//import com.applovin.mediation.MaxAd
//import com.applovin.mediation.MaxAdListener
//import com.applovin.mediation.MaxError
//import com.applovin.mediation.ads.MaxAppOpenAd
//import com.dumpster.cleaner.GlobalConfig
//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.LimitUtils
//
///**
// * 开屏广告加载显示管理类
// */
//class MaxOpenMgr {
//
// private val adState = AdState<MaxAppOpenAd>()
// private var showCallBack: AdsShowCallBack? = null
//
// fun show(activity: Activity, isUnLimit: Boolean, adEvent: AdEvent, showCallBack: AdsShowCallBack?) {
// if (activity.isFinishing || activity.isDestroyed) {
// return
// }
//
// if (showCallBack != null) {
// this.showCallBack = showCallBack
// adEvent.adPrepareShow()
// }
//
// if (!adState.loadingAd) {
//
// if (!isUnLimit) {
// if (!LimitUtils.isAdShow(AdsType.OPEN, adEvent)) {
// showCallBack?.failed()
// return
// }
// if (LimitUtils.isIntervalLimited(adEvent)) {
// showCallBack?.failed()
// return
// }
// }
//
// if (!adAvailable() || adState.currentAd == null) {
// loadAd(activity, isUnLimit, adEvent)
// return
// }
//
// if (adState.currentAd?.isReady != true) {
// loadAd(activity, isUnLimit, adEvent)
// return
// }
// showReadyAd(activity, adEvent)
// }
//
//
// }
//
//
// private fun showReadyAd(activity: Activity, adEvent: AdEvent) {
// adState.currentAd?.run {
// setListener(object : MaxAdListener {
// override fun onAdLoaded(p0: MaxAd) {
//
// }
//
// override fun onAdDisplayed(ad: MaxAd) {
// adState.onAdDisplayed()
// showCallBack?.show()
//
// LimitUtils.addDisplayNum()
// (adEvent as AdMaxEvent).showAd(ad, activity::class.simpleName)
// }
//
// override fun onAdHidden(p0: MaxAd) {
// adState.onAdHidden()
// showCallBack?.close()
// showCallBack = null
//
// loadAd(activity.applicationContext, false, AdMaxEvent("openAd", "preload"))
// }
//
// override fun onAdClicked(ad: MaxAd) {
// (adEvent as AdMaxEvent).clickAd(ad)
// //计数
// LimitUtils.addClickNum()
// }
//
// override fun onAdLoadFailed(p0: String, p1: MaxError) {
//
// }
//
// override fun onAdDisplayFailed(p0: MaxAd, error: MaxError) {
// adState.onAdDisplayFailed()
// showCallBack?.adFailed()
// showCallBack = null
// adEvent.adShowError(error)
// }
//
// })
//
// showAd()
// }
// }
//
// fun loadAd(context: Context, isUnLimit: Boolean, adEvent: AdEvent) {
//
// if (!isUnLimit) {
// if (!LimitUtils.isAdShow(AdsType.OPEN, adEvent)) {
// this.showCallBack?.close()
// this.showCallBack = null
// return
// }
// }
//
// if (!adState.loadingAd) {
// adState.loadingAd = true
//
// adEvent.adPulStart()
//
// adState.currentAd = MaxAppOpenAd(GlobalConfig.ID_MAX_OPEN, context)
// adState.currentAd?.setListener(object : MaxAdListener {
// override fun onAdLoaded(ad: MaxAd) {
//// adState.onAdLoaded(null)
//// val ac = adState.activityRef?.get()
//// if (ac != null) {
//// show(ac, isUnLimit, adEvent, null)
//// }
// (adEvent as AdMaxEvent).pullAd(ad)
// LimitUtils.addRequestNum()
// }
//
// override fun onAdDisplayed(p0: MaxAd) {
//
// }
//
// override fun onAdHidden(p0: MaxAd) {
//
// }
//
// override fun onAdClicked(p0: MaxAd) {
// }
//
// override fun onAdLoadFailed(p0: String, error: MaxError) {
// adState.onAdLoadFailed()
// showCallBack?.adFailed()
// showCallBack = null
// (adEvent as AdMaxEvent).pullAd(null, error)
// }
//
// override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) {
//
// }
//
// })
// adState.currentAd?.loadAd()
// }
// }
//
//
// fun adAvailable() = ((System.currentTimeMillis() - adState.lastLoadTime) / 1000 / 60).toInt() < 30
//}
\ No newline at end of file
......@@ -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
{
"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