Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Sign in / Register
Toggle navigation
A
appzxhy
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wanglei
appzxhy
Commits
ce276060
Commit
ce276060
authored
Jun 26, 2025
by
wanglei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[优化]添加插页场景
parent
e2effc51
Show whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
14622 additions
and
788 deletions
+14622
-788
build.gradle.kts
app/build.gradle.kts
+20
-11
AndroidManifest.xml
app/src/main/AndroidManifest.xml
+6
-0
AdConfigBean.kt
...ain/java/com/dumpster/cleaner/bean/config/AdConfigBean.kt
+4
-2
ConfigBean.kt
.../main/java/com/dumpster/cleaner/bean/config/ConfigBean.kt
+2
-2
AdEvent.kt
...rc/main/java/com/dumpster/cleaner/business/ads/AdEvent.kt
+2
-2
AdState.kt
...rc/main/java/com/dumpster/cleaner/business/ads/AdState.kt
+29
-13
AdsMgr.kt
...src/main/java/com/dumpster/cleaner/business/ads/AdsMgr.kt
+82
-83
LimitUtils.kt
...main/java/com/dumpster/cleaner/business/ads/LimitUtils.kt
+29
-7
AdBannerMgr.kt
...va/com/dumpster/cleaner/business/ads/admob/AdBannerMgr.kt
+3
-4
AdInterMgr.kt
...ava/com/dumpster/cleaner/business/ads/admob/AdInterMgr.kt
+29
-23
AdOpenMgr.kt
...java/com/dumpster/cleaner/business/ads/admob/AdOpenMgr.kt
+42
-30
AdmobEvent.kt
...ava/com/dumpster/cleaner/business/ads/admob/AdmobEvent.kt
+3
-3
AdMaxEvent.kt
.../com/dumpster/cleaner/business/ads/applovin/AdMaxEvent.kt
+157
-157
MaxInsertMgr.kt
...om/dumpster/cleaner/business/ads/applovin/MaxInsertMgr.kt
+169
-169
MaxNativeMgr.kt
...om/dumpster/cleaner/business/ads/applovin/MaxNativeMgr.kt
+115
-115
MaxOpenMgr.kt
.../com/dumpster/cleaner/business/ads/applovin/MaxOpenMgr.kt
+165
-165
JunkCleanActivity.kt
...n/java/com/dumpster/cleaner/ui/clean/JunkCleanActivity.kt
+6
-0
CleanGuideActivity.kt
.../java/com/dumpster/cleaner/ui/guide/CleanGuideActivity.kt
+120
-0
SplashActivity.kt
...ain/java/com/dumpster/cleaner/ui/splash/SplashActivity.kt
+5
-2
guide_pro.xml
app/src/main/res/drawable/guide_pro.xml
+19
-0
activity_layout_clean_guide.xml
app/src/main/res/layout/activity_layout_clean_guide.xml
+108
-0
firstscan.json
app/src/main/res/raw/firstscan.json
+837
-0
firstscan_finish.json
app/src/main/res/raw/firstscan_finish.json
+12670
-0
No files found.
app/build.gradle.kts
View file @
ce276060
...
...
@@ -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
app/src/main/AndroidManifest.xml
View file @
ce276060
...
...
@@ -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"
...
...
app/src/main/java/com/dumpster/cleaner/bean/config/AdConfigBean.kt
View file @
ce276060
...
...
@@ -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
,
//原生展示次数限制
...
...
app/src/main/java/com/dumpster/cleaner/bean/config/ConfigBean.kt
View file @
ce276060
...
...
@@ -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
(),
...
...
app/src/main/java/com/dumpster/cleaner/business/ads/AdEvent.kt
View file @
ce276060
...
...
@@ -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"
)
...
...
app/src/main/java/com/dumpster/cleaner/business/ads/AdState.kt
View file @
ce276060
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
}
app/src/main/java/com/dumpster/cleaner/business/ads/AdsMgr.kt
View file @
ce276060
...
...
@@ -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
)
}
}
...
...
app/src/main/java/com/dumpster/cleaner/business/ads/LimitUtils.kt
View file @
ce276060
...
...
@@ -151,26 +151,48 @@ object LimitUtils {
/**
* 开屏
和插页广告的显示间隔
限制
* 开屏限制
*/
fun
isInterval
Limited
(
adEvent
:
AdEvent
):
Boolean
{
val
flag
=
((
System
.
currentTimeMillis
()
-
open
InterLastShowTime
)
/
1000
).
toInt
()
<
(
AdConfigBean
.
adsConfigBean
.
timeInterval
)
fun
isInterval
OpenLimit
(
adEvent
:
AdEvent
):
Boolean
{
val
flag
=
((
System
.
currentTimeMillis
()
-
open
LastShowTime
)
/
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
(
"open
Inter
LastShowTime"
,
field
)
return
AppPreferences
.
getInstance
().
getLong
(
"openLastShowTime"
,
field
)
}
set
(
value
)
{
field
=
value
AppPreferences
.
getInstance
().
put
(
"open
Inter
LastShowTime"
,
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
)
}
/**
* 原生广告是否到达限制
*/
...
...
app/src/main/java/com/dumpster/cleaner/business/ads/admob/AdBannerMgr.kt
View file @
ce276060
...
...
@@ -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
))
{
...
...
app/src/main/java/com/dumpster/cleaner/business/ads/admob/AdInterMgr.kt
View file @
ce276060
...
...
@@ -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
{
nowA
dEvent
.
reqId
=
it
.
reqId
}
adState
.
currentAdEvent
?.
let
{
a
dEvent
.
reqId
=
it
.
reqId
}
if
(!
nowA
dEvent
.
isUnLimit
)
{
if
(!
LimitUtils
.
isAdShow
(
AdsType
.
INSERT
,
nowA
dEvent
))
{
if
(!
a
dEvent
.
isUnLimit
)
{
if
(!
LimitUtils
.
isAdShow
(
AdsType
.
INSERT
,
a
dEvent
))
{
showCallBack
?.
failed
(
2
)
return
}
if
(
LimitUtils
.
isInterval
Limited
(
nowA
dEvent
))
{
if
(
LimitUtils
.
isInterval
InterLimit
(
a
dEvent
))
{
showCallBack
?.
failed
(
3
)
return
}
...
...
@@ -69,24 +69,29 @@ class AdInterMgr {
adState
.
adDialog
?.
dismiss
()
}
nowA
dEvent
.
adPrepareShow
()
a
dEvent
.
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
,
nowA
dEvent
)
showReadyAd
(
activity
,
a
dEvent
)
}
}
}
else
{
LogEx
.
logDebug
(
adEvent
.
TAG
,
"inter ad ready"
)
showReadyAd
(
activity
,
nowA
dEvent
)
showReadyAd
(
activity
,
a
dEvent
)
}
}
...
...
@@ -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
)
}
...
...
app/src/main/java/com/dumpster/cleaner/business/ads/admob/AdOpenMgr.kt
View file @
ce276060
...
...
@@ -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
(!
nowA
dEvent
.
isUnLimit
)
{
if
(!
LimitUtils
.
isAdShow
(
AdsType
.
OPEN
,
nowA
dEvent
))
{
if
(!
a
dEvent
.
isUnLimit
)
{
if
(!
LimitUtils
.
isAdShow
(
AdsType
.
OPEN
,
a
dEvent
))
{
showCallBack
?.
failed
()
return
}
if
(
LimitUtils
.
isInterval
Limited
(
nowA
dEvent
))
{
if
(
LimitUtils
.
isInterval
OpenLimit
(
a
dEvent
))
{
showCallBack
?.
failed
()
return
}
...
...
@@ -55,26 +55,36 @@ class AdOpenMgr {
val
needLoad
=
!
adState
.
adAvailable
()
this
.
showCallBack
=
showCallBack
nowA
dEvent
.
adPrepareShow
()
a
dEvent
.
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
()
{
ad
Event
?
.
showAd
(
this
@run
.
responseInfo
,
ac
)
ad
mobEvent
.
showAd
(
this
@run
.
responseInfo
,
ac
)
showCallBack
?.
show
()
adState
.
onAdDisplayed
()
adState
.
onAdDisplayed
(
INSERT
)
//计数
LimitUtils
.
addDisplayNum
()
...
...
@@ -105,7 +114,7 @@ class AdOpenMgr {
showCallBack
=
null
adState
.
onAdDisplayFailed
()
ad
Event
?
.
adShowError
(
adError
)
ad
mobEvent
.
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
()
{
ad
Event
?
.
clickAd
(
this
@run
.
responseInfo
)
ad
mobEvent
.
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
)
}
}
...
...
app/src/main/java/com/dumpster/cleaner/business/ads/admob/AdmobEvent.kt
View file @
ce276060
...
...
@@ -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"
)
}
...
...
app/src/main/java/com/dumpster/cleaner/business/ads/applovin/AdMaxEvent.kt
View file @
ce276060
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
app/src/main/java/com/dumpster/cleaner/business/ads/applovin/MaxInsertMgr.kt
View file @
ce276060
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
app/src/main/java/com/dumpster/cleaner/business/ads/applovin/MaxNativeMgr.kt
View file @
ce276060
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
app/src/main/java/com/dumpster/cleaner/business/ads/applovin/MaxOpenMgr.kt
View file @
ce276060
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
app/src/main/java/com/dumpster/cleaner/ui/clean/JunkCleanActivity.kt
View file @
ce276060
...
...
@@ -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
}
})
}
...
...
app/src/main/java/com/dumpster/cleaner/ui/guide/CleanGuideActivity.kt
0 → 100644
View file @
ce276060
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
app/src/main/java/com/dumpster/cleaner/ui/splash/SplashActivity.kt
View file @
ce276060
...
...
@@ -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.
GuideClean
Activity
import
com.dumpster.cleaner.ui.guide.
CleanGuide
Activity
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
(
GuideClean
Activity
::
class
.
java
)
goToAc
(
CleanGuide
Activity
::
class
.
java
)
finish
()
}
...
...
app/src/main/res/drawable/guide_pro.xml
0 → 100644
View file @
ce276060
<?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
app/src/main/res/layout/activity_layout_clean_guide.xml
0 → 100644
View file @
ce276060
<?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
app/src/main/res/raw/firstscan.json
0 → 100644
View file @
ce276060
{
"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
app/src/main/res/raw/firstscan_finish.json
0 → 100644
View file @
ce276060
This source diff could not be displayed because it is too large. You can
view the blob
instead.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment