Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Sign in / Register
Toggle navigation
S
Scan QR Code Barcode Reader
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
Scan QR Code Barcode Reader
Commits
e8ade6bb
Commit
e8ade6bb
authored
Dec 27, 2024
by
wanglei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
...广告
parent
fe134c80
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
40 changed files
with
2847 additions
and
44 deletions
+2847
-44
build.gradle.kts
app/build.gradle.kts
+28
-1
MyApplication.kt
app/src/main/java/com/base/scanqr/MyApplication.kt
+33
-13
AdDialog.kt
app/src/main/java/com/base/scanqr/ads/AdDialog.kt
+41
-0
AdEvent.kt
app/src/main/java/com/base/scanqr/ads/AdEvent.kt
+66
-0
AdsMgr.kt
app/src/main/java/com/base/scanqr/ads/AdsMgr.kt
+259
-0
AdsShowCallBack.kt
app/src/main/java/com/base/scanqr/ads/AdsShowCallBack.kt
+7
-0
AdsType.kt
app/src/main/java/com/base/scanqr/ads/AdsType.kt
+22
-0
BaseAdMgr.kt
app/src/main/java/com/base/scanqr/ads/BaseAdMgr.kt
+146
-0
LimitUtils.kt
app/src/main/java/com/base/scanqr/ads/LimitUtils.kt
+146
-0
NativeParentView.kt
app/src/main/java/com/base/scanqr/ads/NativeParentView.kt
+88
-0
AdBannerMgr.kt
app/src/main/java/com/base/scanqr/ads/admob/AdBannerMgr.kt
+94
-0
AdInsertMgr.kt
app/src/main/java/com/base/scanqr/ads/admob/AdInsertMgr.kt
+157
-0
AdNativeMgr.kt
app/src/main/java/com/base/scanqr/ads/admob/AdNativeMgr.kt
+102
-0
AdOpenMgr.kt
app/src/main/java/com/base/scanqr/ads/admob/AdOpenMgr.kt
+150
-0
AdmobEvent.kt
app/src/main/java/com/base/scanqr/ads/admob/AdmobEvent.kt
+308
-0
AdMaxEvent.kt
app/src/main/java/com/base/scanqr/ads/applovin/AdMaxEvent.kt
+157
-0
MaxInsertMgr.kt
...rc/main/java/com/base/scanqr/ads/applovin/MaxInsertMgr.kt
+178
-0
MaxNativeMgr.kt
...rc/main/java/com/base/scanqr/ads/applovin/MaxNativeMgr.kt
+115
-0
MaxOpenMgr.kt
app/src/main/java/com/base/scanqr/ads/applovin/MaxOpenMgr.kt
+173
-0
ConstObject.kt
app/src/main/java/com/base/scanqr/bean/ConstObject.kt
+9
-0
AdConfigBean.kt
...src/main/java/com/base/scanqr/bean/config/AdConfigBean.kt
+12
-0
ConfigBean.kt
app/src/main/java/com/base/scanqr/bean/config/ConfigBean.kt
+18
-0
PopupConfigBean.kt
.../main/java/com/base/scanqr/bean/config/PopupConfigBean.kt
+36
-0
FCMManager.kt
app/src/main/java/com/base/scanqr/fcm/FCMManager.kt
+73
-0
AppConfig.kt
app/src/main/java/com/base/scanqr/helper/AppConfig.kt
+0
-25
EventUtils.kt
app/src/main/java/com/base/scanqr/helper/EventUtils.kt
+4
-3
CameraUtils.kt
app/src/main/java/com/base/scanqr/qr/CameraUtils.kt
+0
-1
MainActivity.kt
app/src/main/java/com/base/scanqr/ui/main/MainActivity.kt
+15
-1
NotificationDialog.kt
...main/java/com/base/scanqr/ui/widget/NotificationDialog.kt
+53
-0
bg_6379e6_35.xml
app/src/main/res/drawable/bg_6379e6_35.xml
+5
-0
bg_ff8a00_10.xml
app/src/main/res/drawable/bg_ff8a00_10.xml
+5
-0
dialog_ad_preparing.xml
app/src/main/res/layout/dialog_ad_preparing.xml
+39
-0
dialog_notification_turn_on.xml
app/src/main/res/layout/dialog_notification_turn_on.xml
+69
-0
layout_admob_native_custom.xml
app/src/main/res/layout/layout_admob_native_custom.xml
+100
-0
layout_max_native_custom.xml
app/src/main/res/layout/layout_max_native_custom.xml
+113
-0
icon_close.png
app/src/main/res/mipmap-xxhdpi/icon_close.png
+0
-0
img_tongzhi_pop_bj.png
app/src/main/res/mipmap-xxhdpi/img_tongzhi_pop_bj.png
+0
-0
jiazai_ad.webp
app/src/main/res/mipmap-xxhdpi/jiazai_ad.webp
+0
-0
strings.xml
app/src/main/res/values/strings.xml
+4
-0
libs.versions.toml
gradle/libs.versions.toml
+22
-0
No files found.
app/build.gradle.kts
View file @
e8ade6bb
...
@@ -77,7 +77,6 @@ dependencies {
...
@@ -77,7 +77,6 @@ dependencies {
androidTestImplementation
(
libs
.
androidx
.
junit
)
androidTestImplementation
(
libs
.
androidx
.
junit
)
androidTestImplementation
(
libs
.
androidx
.
espresso
.
core
)
androidTestImplementation
(
libs
.
androidx
.
espresso
.
core
)
//网络请求
//网络请求
implementation
(
"com.google.code.gson:gson:2.11.0"
)
implementation
(
"com.google.code.gson:gson:2.11.0"
)
...
@@ -89,6 +88,8 @@ dependencies {
...
@@ -89,6 +88,8 @@ dependencies {
api
(
libs
.
immersionbar
.
ktx
)
api
(
libs
.
immersionbar
.
ktx
)
//facebook
implementation
(
"com.facebook.android:facebook-android-sdk:[8,9)"
)
//solar 归因
//solar 归因
implementation
(
"com.reyun.solar.engine.oversea:solar-engine-core:1.2.8.3"
)
implementation
(
"com.reyun.solar.engine.oversea:solar-engine-core:1.2.8.3"
)
...
@@ -113,5 +114,31 @@ dependencies {
...
@@ -113,5 +114,31 @@ dependencies {
// implementation("com.google.zxing:android-integration:$zxing")
// implementation("com.google.zxing:android-integration:$zxing")
// implementation("com.google.zxing:zxing-android-embedded:$zxing")
// implementation("com.google.zxing:zxing-android-embedded:$zxing")
//广告
//admob渠道
implementation
(
libs
.
vungle
)
implementation
(
libs
.
facebook
)
implementation
(
libs
.
mintegral
)
implementation
(
libs
.
pangle
)
//applovin sdk
implementation
(
libs
.
applovin
)
//applovin渠道
implementation
(
libs
.
applovin
.
google
)
implementation
(
libs
.
applovin
.
admob
)
implementation
(
libs
.
applovin
.
facebook
)
//meta
implementation
(
libs
.
applovin
.
mintegral
)
//mintegral
implementation
(
libs
.
applovin
.
pangle
)
//pangle
implementation
(
libs
.
applovin
.
vungle
)
//vungle
//firebase
implementation
(
platform
(
"com.google.firebase:firebase-bom:32.3.1"
))
implementation
(
"com.google.firebase:firebase-messaging"
)
implementation
(
"com.google.firebase:firebase-analytics-ktx"
)
implementation
(
"com.google.firebase:firebase-crashlytics"
)
implementation
(
"com.google.firebase:firebase-config"
)
//冲突版本确定版本
implementation
(
"com.google.guava:guava:29.0-android"
)
}
}
app/src/main/java/com/base/scanqr/MyApplication.kt
View file @
e8ade6bb
...
@@ -6,12 +6,15 @@ import android.content.Context
...
@@ -6,12 +6,15 @@ import android.content.Context
import
android.os.Bundle
import
android.os.Bundle
import
android.text.TextUtils
import
android.text.TextUtils
import
android.util.Log
import
android.util.Log
import
com.base.scanqr.ads.AdsMgr
import
com.base.scanqr.bean.ConstObject.appLanguageCountrySp
import
com.base.scanqr.bean.ConstObject.appLanguageCountrySp
import
com.base.scanqr.bean.ConstObject.appLanguageSp
import
com.base.scanqr.bean.ConstObject.appLanguageSp
import
com.base.scanqr.
helper.AppConfig
import
com.base.scanqr.
fcm.FCMManager
import
com.base.scanqr.utils.ActivityManagerUtils
import
com.base.scanqr.utils.ActivityManagerUtils
import
com.base.scanqr.utils.AppPreferences
import
com.base.scanqr.utils.AppPreferences
import
com.base.scanqr.utils.LogEx
import
com.base.scanqr.utils.LogEx
import
com.facebook.FacebookSdk
import
com.google.android.gms.ads.identifier.AdvertisingIdClient
import
com.hjq.language.MultiLanguages
import
com.hjq.language.MultiLanguages
import
com.hjq.language.OnLanguageListener
import
com.hjq.language.OnLanguageListener
import
java.util.Locale
import
java.util.Locale
...
@@ -20,7 +23,7 @@ import java.util.UUID
...
@@ -20,7 +23,7 @@ import java.util.UUID
class
MyApplication
:
Application
()
{
class
MyApplication
:
Application
()
{
private
val
TAG
=
"MyApplication"
private
val
TAG
=
"MyApplication"
var
uuid
=
""
private
var
uuid
=
""
companion
object
{
companion
object
{
...
@@ -28,6 +31,15 @@ class MyApplication : Application() {
...
@@ -28,6 +31,15 @@ class MyApplication : Application() {
@JvmField
@JvmField
var
PAUSED_VALUE
=
0
var
PAUSED_VALUE
=
0
val
noLoadingActivities
=
listOf
(
"full"
,
// 过滤全屏广告
"adActivity"
,
"AdActivity"
,
"AppLovinFullscreenActivity"
,
// SplashActivity::class.java.simpleName,
// 返回前台时不跳转启动页的 activity
)
}
}
...
@@ -35,11 +47,11 @@ class MyApplication : Application() {
...
@@ -35,11 +47,11 @@ class MyApplication : Application() {
super
.
onCreate
()
super
.
onCreate
()
appContext
=
this
appContext
=
this
initUUid
()
initUUid
()
initGid
()
initApp
()
initApp
()
// 初始化语种切换框架
// 初始化语种切换框架
MultiLanguages
.
init
(
this
)
MultiLanguages
.
init
(
this
)
// 设置语种变化监听器
// 设置语种变化监听器
MultiLanguages
.
setOnLanguageListener
(
object
:
OnLanguageListener
{
MultiLanguages
.
setOnLanguageListener
(
object
:
OnLanguageListener
{
override
fun
onAppLocaleChange
(
oldLocale
:
Locale
,
newLocale
:
Locale
)
{
override
fun
onAppLocaleChange
(
oldLocale
:
Locale
,
newLocale
:
Locale
)
{
...
@@ -71,16 +83,24 @@ class MyApplication : Application() {
...
@@ -71,16 +83,24 @@ class MyApplication : Application() {
LogEx
.
logDebug
(
TAG
,
"uuid=${AppPreferences.getInstance().getString("
uuid
", "")}"
)
LogEx
.
logDebug
(
TAG
,
"uuid=${AppPreferences.getInstance().getString("
uuid
", "")}"
)
}
}
private
fun
initGid
()
{
Thread
{
val
info
:
AdvertisingIdClient
.
Info
=
AdvertisingIdClient
.
getAdvertisingIdInfo
(
applicationContext
)
val
advertisingId
=
info
.
id
AppPreferences
.
getInstance
().
put
(
"gid"
,
advertisingId
)
}.
start
()
}
private
fun
initApp
()
{
private
fun
initApp
()
{
//初始化广告相关业务
//初始化广告相关业务
//
AdsMgr.init(appContext)
AdsMgr
.
init
(
appContext
)
//
FacebookSdk.sdkInitialize(applicationContext)
FacebookSdk
.
sdkInitialize
(
applicationContext
)
//
val token = AppPreferences.getInstance().getString("token", "")
val
token
=
AppPreferences
.
getInstance
().
getString
(
"token"
,
""
)
// val topic = AppConfig.packageName
+ "_push"
val
topic
=
GlobalConfig
.
PACKAGE_NAME
+
"_push"
//
LogEx.logDebug(TAG, "topic=${topic} token=$token")
LogEx
.
logDebug
(
TAG
,
"topic=${topic} token=$token"
)
//
FCMManager.initFirebase(this)
FCMManager
.
initFirebase
(
this
)
//
FCMManager.subscribeToTopic(topic)
FCMManager
.
subscribeToTopic
(
topic
)
// initConfig()
// initConfig()
//
//
...
@@ -131,7 +151,7 @@ class MyApplication : Application() {
...
@@ -131,7 +151,7 @@ class MyApplication : Application() {
val
flag
=
if
(
topActivity
==
null
)
{
val
flag
=
if
(
topActivity
==
null
)
{
true
true
}
else
{
}
else
{
AppConfig
.
noLoadingActivities
.
all
{
!
topActivity
.
localClassName
.
contains
(
it
,
true
)
}
noLoadingActivities
.
all
{
!
topActivity
.
localClassName
.
contains
(
it
,
true
)
}
}
}
LogEx
.
logDebug
(
TAG
,
"flag=$flag"
+
" activity:"
+
activity
.
localClassName
)
LogEx
.
logDebug
(
TAG
,
"flag=$flag"
+
" activity:"
+
activity
.
localClassName
)
...
@@ -199,8 +219,8 @@ class MyApplication : Application() {
...
@@ -199,8 +219,8 @@ class MyApplication : Application() {
// ConfigBean.configBean = configBean
// ConfigBean.configBean = configBean
//
//
// //广告
// //广告
// AdsMgr.adsConfigBean = configBean.adConfigBean
//
com.base.scanqr.ads.
AdsMgr.adsConfigBean = configBean.adConfigBean
// com.base.localweatherwhite.utils.LogEx.logDebug("initConfig", "AdsMgr.adsConfigBean=${configBean.adConfigBean.functionInShowAd}")
// com.base.localweatherwhite.utils.LogEx.logDebug("initConfig", "
com.base.scanqr.ads.
AdsMgr.adsConfigBean=${configBean.adConfigBean.functionInShowAd}")
//
//
// //通知
// //通知
// PopupConstObject.popupConfigBean = configBean.popupConfigBean
// PopupConstObject.popupConfigBean = configBean.popupConfigBean
...
...
app/src/main/java/com/base/scanqr/ads/AdDialog.kt
0 → 100644
View file @
e8ade6bb
package
com.base.scanqr.ads
import
android.animation.ObjectAnimator
import
android.animation.ValueAnimator.INFINITE
import
android.app.AlertDialog
import
android.content.Context
import
android.view.LayoutInflater
import
android.view.animation.LinearInterpolator
import
com.base.scanqr.databinding.DialogAdPreparingBinding
import
com.base.scanqr.utils.DensityUtils
import
com.base.scanqr.utils.LogEx
object
AdDialog
{
private
val
TAG
=
"AdDialog"
fun
Context
.
showAdPreparingDialog
(
where
:
Int
=
0
):
AlertDialog
{
LogEx
.
logDebug
(
TAG
,
"where=$where"
)
val
binding
=
DialogAdPreparingBinding
.
inflate
(
LayoutInflater
.
from
(
this
))
val
dialog
=
AlertDialog
.
Builder
(
this
).
create
()
dialog
.
setView
(
binding
.
root
)
dialog
.
setCancelable
(
false
)
dialog
.
setCanceledOnTouchOutside
(
false
)
dialog
.
show
()
val
params
=
dialog
.
window
?.
attributes
params
?.
width
=
DensityUtils
.
dip2px
(
200f
)
params
?.
height
=
DensityUtils
.
dip2px
(
146f
)
dialog
.
window
?.
attributes
=
params
dialog
.
window
?.
setBackgroundDrawableResource
(
android
.
R
.
color
.
transparent
)
// 创建一个旋转动画
val
rotateAnimator
=
ObjectAnimator
.
ofFloat
(
binding
.
iv
,
"rotation"
,
0f
,
-
360f
)
rotateAnimator
.
setDuration
(
1000
)
// 设置动画持续时间为1000毫秒
rotateAnimator
.
repeatCount
=
INFINITE
rotateAnimator
.
interpolator
=
LinearInterpolator
()
// 设置插值器为线性插值
rotateAnimator
.
start
()
return
dialog
}
}
\ No newline at end of file
app/src/main/java/com/base/scanqr/ads/AdEvent.kt
0 → 100644
View file @
e8ade6bb
package
com.base.scanqr.ads
import
com.base.scanqr.MyApplication
import
com.base.scanqr.helper.EventUtils
import
com.base.scanqr.utils.LogEx
import
org.json.JSONObject
import
java.util.UUID
val
taichiPref
by
lazy
{
MyApplication
.
appContext
.
getSharedPreferences
(
"TaichiTroasCache"
,
0
)
}
val
taichiSharedPreferencesEditor
by
lazy
{
taichiPref
.
edit
()
}
abstract
class
AdEvent
{
abstract
val
TAG
:
String
var
adUnit
:
String
=
""
var
from
:
String
=
""
val
reqId
=
UUID
.
randomUUID
().
toString
()
fun
adPrepareShow
()
{
val
obj1
=
JSONObject
()
obj1
.
put
(
"ad_unit"
,
adUnit
)
obj1
.
put
(
"req_id"
,
reqId
)
obj1
.
put
(
"from"
,
from
)
EventUtils
.
event
(
"ad_prepare_show"
,
ext
=
obj1
)
LogEx
.
logDebug
(
TAG
,
"ad_prepare_show $obj1"
)
}
fun
adPulStart
()
{
val
obj
=
JSONObject
()
obj
.
put
(
"req_id"
,
reqId
)
obj
.
put
(
"ad_unit"
,
adUnit
)
obj
.
put
(
"ad_type"
,
adUnit
)
obj
.
put
(
"from"
,
from
)
EventUtils
.
event
(
"ad_pull_start"
,
ext
=
obj
)
LogEx
.
logDebug
(
TAG
,
"ad_pull_start $obj"
)
}
fun
adShowError
(
reason
:
Any
)
{
val
obj
=
JSONObject
()
obj
.
put
(
"ad_unit"
,
adUnit
)
obj
.
put
(
"req_id"
,
reqId
)
obj
.
put
(
"from"
,
from
)
obj
.
put
(
"reason"
,
reason
.
toString
())
EventUtils
.
event
(
"ad_show_error"
,
ext
=
obj
)
LogEx
.
logDebug
(
TAG
,
"ad_show_error $obj"
)
}
fun
adLimited
(
value
:
String
)
{
val
obj
=
JSONObject
()
obj
.
put
(
"ad_unit"
,
adUnit
)
obj
.
put
(
"req_id"
,
reqId
)
obj
.
put
(
"from"
,
from
)
EventUtils
.
event
(
"ad_limit"
,
value
,
obj
)
LogEx
.
logDebug
(
TAG
,
"ad_limit $obj"
)
}
}
\ No newline at end of file
app/src/main/java/com/base/scanqr/ads/AdsMgr.kt
0 → 100644
View file @
e8ade6bb
package
com.base.scanqr.ads
import
android.app.Activity
import
android.content.Context
import
android.view.ViewGroup
import
androidx.annotation.LayoutRes
import
com.applovin.sdk.AppLovinMediationProvider
import
com.applovin.sdk.AppLovinSdk
import
com.applovin.sdk.AppLovinSdkInitializationConfiguration
import
com.base.appzxhy.bean.config.ConfigBean.Companion.configBean
import
com.base.scanqr.BuildConfig
import
com.base.scanqr.GlobalConfig
import
com.base.scanqr.ads.admob.AdBannerMgr
import
com.base.scanqr.ads.admob.AdInsertMgr
import
com.base.scanqr.ads.admob.AdNativeMgr
import
com.base.scanqr.ads.admob.AdOpenMgr
import
com.base.scanqr.ads.admob.AdmobEvent
import
com.base.scanqr.ads.applovin.AdMaxEvent
import
com.base.scanqr.ads.applovin.MaxInsertMgr
import
com.base.scanqr.ads.applovin.MaxNativeMgr
import
com.base.scanqr.ads.applovin.MaxOpenMgr
import
com.base.scanqr.bean.config.AdConfigBean
import
com.base.scanqr.helper.EventUtils
import
com.base.scanqr.utils.AppPreferences
import
com.base.scanqr.utils.LogEx
import
com.base.scanqr.utils.ToastUtils.toast
import
com.google.android.gms.ads.MobileAds
import
com.google.android.gms.ads.identifier.AdvertisingIdClient
import
com.google.android.gms.ads.initialization.AdapterStatus
import
java.util.Collections
import
java.util.concurrent.Executors
/**
* 广告管理类
*/
object
AdsMgr
{
private
val
adOpenMgr
by
lazy
{
AdOpenMgr
()
}
private
val
adInsertMgr
by
lazy
{
AdInsertMgr
()
}
private
val
adNativeMgr
by
lazy
{
AdNativeMgr
()
}
private
val
adBannerMgr
by
lazy
{
AdBannerMgr
()
}
private
val
maxOpenMgr
by
lazy
{
MaxOpenMgr
()
}
private
val
maxInsertMgr
by
lazy
{
MaxInsertMgr
()
}
private
val
maxNativeMgr
by
lazy
{
MaxNativeMgr
()
}
/**
* 是否初始化
*/
var
isAdmobInit
=
false
private
set
/**
* 是否初始化
*/
var
isMaxInit
=
false
private
set
/**
* 广告配置项目
*/
var
adsConfigBean
:
AdConfigBean
=
AdConfigBean
()
/**
* Init 初始化
*
* @param context 这里最好是appContext,因为是耗时操作,等它初始化完毕马上加载开屏和插屏广告
*/
fun
init
(
context
:
Context
)
{
if
(
configBean
.
isInBlackList
)
{
EventUtils
.
event
(
"isInBlackList"
,
configBean
.
isInBlackList
.
toString
())
return
}
initAdmob
(
context
)
initMax
(
context
)
}
private
fun
initAdmob
(
context
:
Context
)
{
MobileAds
.
initialize
(
context
)
{
val
readyAdapter
=
it
.
adapterStatusMap
.
entries
.
find
{
entry
->
entry
.
value
.
initializationState
==
AdapterStatus
.
State
.
READY
}
isAdmobInit
=
readyAdapter
!=
null
EventUtils
.
event
(
"AdmobInit"
,
"AdmobInit"
)
// context.toast("admob init")
if
(
adsConfigBean
.
adSwitch
)
{
admobInitCallBack
?.
invoke
()
admobInitCallBack
=
null
adOpenMgr
.
loadAd
(
context
,
false
,
AdmobEvent
(
"openAd"
,
context
::
class
.
java
.
simpleName
))
adInsertMgr
.
loadAd
(
context
,
false
,
AdmobEvent
(
"interAd"
,
context
::
class
.
java
.
simpleName
))
}
}
}
private
fun
initMax
(
context
:
Context
)
=
kotlin
.
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
.
setMediationProvider
(
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
,
false
,
AdMaxEvent
(
"interAd"
,
context
::
class
.
java
.
simpleName
))
context
.
toast
(
"max init"
)
maxInitCallBack
?.
invoke
()
maxInitCallBack
=
null
}
}
}
}
}
private
var
admobInitCallBack
:
(()
->
Unit
)?
=
null
private
var
maxInitCallBack
:
(()
->
Unit
)?
=
null
/**
* 展示开屏广告
*
* @param activity 当前页面
* @param showCallBack 展示回调
*/
fun
showOpen
(
activity
:
Activity
,
isUnLimit
:
Boolean
=
false
,
showCallBack
:
AdsShowCallBack
?
=
null
,
)
{
if
(
configBean
.
isInBlackList
)
{
EventUtils
.
event
(
"isInBlackList"
,
"isInBlackList=${configBean.isInBlackList}"
)
return
}
val
from
=
activity
::
class
.
java
.
simpleName
if
(
adsConfigBean
.
adSwitch
)
{
if
(
isAdmobInit
)
{
adOpenMgr
.
show
(
activity
,
isUnLimit
,
AdmobEvent
(
"openAd"
,
from
),
showCallBack
)
}
else
{
admobInitCallBack
=
{
}
adOpenMgr
.
show
(
activity
,
isUnLimit
,
AdmobEvent
(
"openAd"
,
from
),
showCallBack
)
}
}
else
{
if
(
isMaxInit
)
{
maxOpenMgr
.
show
(
activity
,
isUnLimit
,
AdMaxEvent
(
"openAd"
,
from
),
showCallBack
)
}
else
{
maxInitCallBack
=
{
maxOpenMgr
.
show
(
activity
,
isUnLimit
,
AdMaxEvent
(
"openAd"
,
from
),
showCallBack
)
}
}
}
}
/**
* 展示插屏广告
*
* @param activity 当前页面
* @param showCallBack 展示回调
* @param isUnLimit 是否不受限制 默认false 代表受到限制
*/
fun
showInsert
(
activity
:
Activity
,
isUnLimit
:
Boolean
=
false
,
showCallBack
:
AdsShowCallBack
?
=
null
,
)
{
if
(
configBean
.
isInBlackList
)
{
EventUtils
.
event
(
"isInBlackList"
,
configBean
.
isInBlackList
.
toString
())
return
}
LogEx
.
logDebug
(
"showAd"
,
"adSwitch=${adsConfigBean.adSwitch}"
)
val
from
=
activity
::
class
.
java
.
simpleName
if
(
adsConfigBean
.
adSwitch
)
{
adInsertMgr
.
show
(
activity
,
isUnLimit
,
AdmobEvent
(
"interAd"
,
from
),
showCallBack
)
}
else
{
maxInsertMgr
.
show
(
activity
,
isUnLimit
,
AdMaxEvent
(
"interAd"
,
from
),
showCallBack
)
}
}
/**
* 展示原生广告
*
* @param nativeView 需要展示广告的布局容器
* @param layout 原生广告布局 ,这里传入的layout要和com.example.mydemo.strategy.ads.admob.NativeView里的id一致
*/
fun
showNative
(
nativeView
:
NativeParentView
,
@LayoutRes
layout
:
Int
,
nativeCallBack
:
((
Any
?)
->
Unit
)?
=
null
)
{
if
(
configBean
.
isInBlackList
)
{
EventUtils
.
event
(
"isInBlackList"
,
configBean
.
isInBlackList
.
toString
())
return
}
if
(!
isAdmobInit
)
return
if
(
adsConfigBean
.
adSwitch
)
{
adNativeMgr
.
show
(
AdmobEvent
(
"nativeAd"
,
"nativeAd"
),
nativeView
,
layout
,
nativeCallBack
)
}
else
{
maxNativeMgr
.
show
(
AdMaxEvent
(
"nativeAd"
,
"nativeAd"
),
nativeView
,
layout
,
nativeCallBack
)
}
}
fun
isNativeShow
()
=
(
isAdmobInit
&&
!
configBean
.
isInBlackList
)
&&
LimitUtils
.
isAdShow
(
AdsType
.
NATIVE
,
null
)
/**
* 展示banner广告
*
* @param parent 展示广告的父布局容器
*/
fun
showBanner
(
parent
:
ViewGroup
,
collapsible
:
Boolean
=
true
,
adClose
:
(()
->
Unit
)?
=
null
)
{
if
(
configBean
.
isInBlackList
)
{
EventUtils
.
event
(
"isInBlackList"
,
configBean
.
isInBlackList
.
toString
())
return
}
if
(
adsConfigBean
.
adSwitch
)
{
adBannerMgr
.
show
(
parent
,
collapsible
,
adClose
)
}
}
}
\ No newline at end of file
app/src/main/java/com/base/scanqr/ads/AdsShowCallBack.kt
0 → 100644
View file @
e8ade6bb
package
com.base.scanqr.ads
abstract
class
AdsShowCallBack
{
open
fun
show
()
{}
abstract
fun
close
(
where
:
Int
=
0
)
abstract
fun
failed
(
where
:
Int
=
0
)
abstract
fun
googleFailed
(
where
:
Int
=
0
)
}
\ No newline at end of file
app/src/main/java/com/base/scanqr/ads/AdsType.kt
0 → 100644
View file @
e8ade6bb
package
com.base.scanqr.ads
/**
* 广告类型
* 0=开屏广告、1=插屏广告、2=原生广告、3=Banner横幅广告
*/
@JvmInline
value
class
AdsType
private
constructor
(
val
value
:
Int
)
{
companion
object
{
val
OPEN
=
AdsType
(
0
)
val
INSERT
=
AdsType
(
1
)
val
NATIVE
=
AdsType
(
2
)
val
BANNER
=
AdsType
(
3
)
fun
from
(
adsType
:
Int
):
AdsType
{
return
when
(
adsType
)
{
OPEN
.
value
->
OPEN
INSERT
.
value
->
INSERT
NATIVE
.
value
->
NATIVE
else
->
BANNER
}
}
}
}
\ No newline at end of file
app/src/main/java/com/base/scanqr/ads/BaseAdMgr.kt
0 → 100644
View file @
e8ade6bb
package
com.base.scanqr.ads
import
android.app.Activity
import
android.app.Dialog
import
android.content.Context
import
java.lang.ref.WeakReference
class
adState
<
T
>()
{
var
adDialog
:
Dialog
?
=
null
/**
* 当前缓存的广告
*/
var
currentAd
:
T
?
=
null
/**
* 是否正在缓存加载广告
*/
var
loadingAd
:
Boolean
=
false
/**
* 是否正在显示广告
*/
var
showingAd
:
Boolean
=
false
/**
* 用于保存引用现有页面,在此页面显示广告(因为要等待广告加载完毕)
*/
var
activityRef
:
WeakReference
<
Activity
>?
=
null
/**
* 上一次的缓存成功时间
*/
var
lastLoadTime
:
Long
=
0
/**
* 上次展示时间
*/
var
lastShowTime
:
Long
=
0
fun
onAdDisplayed
()
{
showingAd
=
true
adDialog
?.
dismiss
()
adDialog
=
null
lastShowTime
=
System
.
currentTimeMillis
()
currentAd
=
null
activityRef
=
null
}
fun
onAdHidden
()
{
// 广告关闭,清空缓存数据,重新加载
showingAd
=
false
}
fun
onAdDisplayFailed
()
{
adDialog
?.
dismiss
()
adDialog
=
null
showingAd
=
false
currentAd
=
null
activityRef
=
null
}
fun
onAdLoaded
(
ad
:
T
?)
{
//这里可能提前设置,所有可以不设置,max回调的类型可能不同
if
(
ad
!=
null
)
{
currentAd
=
ad
}
loadingAd
=
false
lastLoadTime
=
System
.
currentTimeMillis
()
}
fun
onAdLoadFailed
()
{
adDialog
?.
dismiss
()
adDialog
=
null
loadingAd
=
false
}
}
/**
* 特定广告管理基类
* @param T 缓存广告的类
*/
abstract
class
BaseAdMgr
<
T
>
{
/**
* 广告展示回调
*/
protected
var
showCallBack
:
AdsShowCallBack
?
=
null
/**
* 当前缓存的广告
*/
protected
var
currentAd
:
T
?
=
null
/**
* 是否正在缓存加载广告
*/
protected
var
loadingAd
:
Boolean
=
false
/**
* 是否正在显示广告
*/
protected
var
showingAd
:
Boolean
=
false
/**
* 用于保存引用现有页面,在此页面显示广告(因为要等待广告加载完毕)
*/
protected
var
activityRef
:
WeakReference
<
Activity
>?
=
null
/**
* 上一次的缓存成功时间
*/
protected
var
lastLoadTime
:
Long
=
0
/**
* 预加载广告
*
* @param context 加载所用的上下文,一般使用appContext
*/
abstract
fun
loadAd
(
context
:
Context
,
isUnLimit
:
Boolean
=
true
,
adEvent
:
AdEvent
)
/**
* 广告显示
*
* @param activity 当前页面
*/
abstract
fun
show
(
activity
:
Activity
,
isUnLimit
:
Boolean
=
true
,
adEvent
:
AdEvent
,
showCallBack
:
AdsShowCallBack
?
=
null
)
/**
* 预加载的缓存超时判断
*
* @return true:没有超时 false:超时需要重新加载
*/
abstract
fun
adAvailable
():
Boolean
}
\ No newline at end of file
app/src/main/java/com/base/scanqr/ads/LimitUtils.kt
0 → 100644
View file @
e8ade6bb
package
com.base.scanqr.ads
import
com.base.scanqr.utils.AppPreferences
import
com.base.scanqr.utils.KotlinExt.toFormatTime4
/**
* 控制广告计数与判断显示条件
*
*/
object
LimitUtils
{
const
val
NUM_DISPLAY
=
"local_numDisplayLimit"
const
val
NUM_REQUEST
=
"local_numRequestLimit"
const
val
NUM_CLICK
=
"local_numClickLimit"
const
val
SAVE_DATE
=
"local_SAVE_DATE"
/**
* 保存的时间,用来判断是否是当天,不是当天要重置计数次数
*/
private
var
saveDate
get
()
=
AppPreferences
.
getInstance
()
.
getString
(
SAVE_DATE
,
System
.
currentTimeMillis
().
toFormatTime4
())
set
(
value
)
=
AppPreferences
.
getInstance
().
put
(
SAVE_DATE
,
value
)
/**
* 广告请求是否到达限制
*/
private
inline
val
isRequestLimited
:
Boolean
get
()
{
val
maxCount
=
AdsMgr
.
adsConfigBean
.
numRequestLimit
return
maxCount
>
-
1
&&
AppPreferences
.
getInstance
()
.
getInt
(
NUM_REQUEST
,
0
)
>=
maxCount
}
/**
* 广告展示是否到达限制
*/
private
inline
val
isDisplayLimited
:
Boolean
get
()
{
val
maxCount
=
AdsMgr
.
adsConfigBean
.
numDisplayLimit
return
maxCount
>
-
1
&&
AppPreferences
.
getInstance
()
.
getInt
(
NUM_DISPLAY
,
0
)
>=
maxCount
}
/**
* 广告点击是否到达限制
*/
private
inline
val
isClickLimited
:
Boolean
get
()
{
val
maxCount
=
AdsMgr
.
adsConfigBean
.
numClickLimit
return
maxCount
>
-
1
&&
AppPreferences
.
getInstance
()
.
getInt
(
NUM_CLICK
,
0
)
>=
maxCount
}
private
fun
getAdEventMsg
(
adsType
:
AdsType
):
String
{
return
when
(
adsType
)
{
AdsType
.
OPEN
->
"Open"
AdsType
.
INSERT
->
"Inter"
AdsType
.
NATIVE
->
"Native"
else
->
"Banner"
}
}
/**
* 是否显示广告
*
* @return true or false
*/
fun
isAdShow
(
adsType
:
AdsType
,
adEvent
:
AdEvent
?):
Boolean
{
val
currentDate
=
System
.
currentTimeMillis
().
toFormatTime4
()
if
(
saveDate
!=
currentDate
)
{
//如果已经不是今天了,就重置个数
saveDate
=
currentDate
AppPreferences
.
getInstance
().
put
(
NUM_DISPLAY
,
0
)
AppPreferences
.
getInstance
().
put
(
NUM_REQUEST
,
0
)
AppPreferences
.
getInstance
().
put
(
NUM_CLICK
,
0
)
}
if
(
isDisplayLimited
)
{
val
value
=
"current${getAdEventMsg(adsType)} "
+
"show=${AppPreferences.getInstance().getInt(NUM_DISPLAY, 0)} "
+
"${getAdEventMsg(adsType).lowercase()}_"
+
"max_show=${AdsMgr.adsConfigBean.numDisplayLimit}"
adEvent
?.
adLimited
(
value
)
}
if
(
isClickLimited
)
{
val
value
=
"current${getAdEventMsg(adsType)}Click=${AppPreferences.getInstance().getInt(NUM_CLICK, 0)} "
"${getAdEventMsg(adsType).lowercase()}_max_click=${AdsMgr.adsConfigBean.numClickLimit}"
adEvent
?.
adLimited
(
value
)
}
if
(
isRequestLimited
)
{
val
value
=
"current${getAdEventMsg(adsType)}Request=${AppPreferences.getInstance().getInt(NUM_REQUEST, 0)} "
+
"${getAdEventMsg(adsType).lowercase()}_max_request=${AdsMgr.adsConfigBean.numRequestLimit}"
adEvent
?.
adLimited
(
value
)
}
return
!(
isDisplayLimited
||
isClickLimited
||
isRequestLimited
)
}
private
fun
addNum
(
key
:
String
)
{
val
currentDate
=
System
.
currentTimeMillis
().
toFormatTime4
()
if
(
saveDate
!=
currentDate
)
{
//如果已经不是今天了,就重置个数
saveDate
=
currentDate
AppPreferences
.
getInstance
().
put
(
key
,
1
)
return
}
AppPreferences
.
getInstance
()
.
put
(
key
,
(
AppPreferences
.
getInstance
().
getInt
(
key
,
0
)
+
1
))
}
fun
addDisplayNum
()
{
addNum
(
NUM_DISPLAY
)
}
fun
addRequestNum
()
{
addNum
(
NUM_REQUEST
)
}
fun
addClickNum
()
{
addNum
(
NUM_CLICK
)
}
/**
* 开屏和插页广告的显示间隔限制
*
* @param lastTime 上一次显示的时间
*/
fun
isIntervalLimited
(
lastTime
:
Long
,
adEvent
:
AdEvent
):
Boolean
{
val
flag
=
((
System
.
currentTimeMillis
()
-
lastTime
)
/
1000
).
toInt
()
<
(
AdsMgr
.
adsConfigBean
.
timeInterval
)
if
(
flag
)
{
adEvent
.
adShowError
(
"ad in timeInterval"
)
}
return
flag
}
}
\ No newline at end of file
app/src/main/java/com/base/scanqr/ads/NativeParentView.kt
0 → 100644
View file @
e8ade6bb
package
com.base.scanqr.ads
import
android.annotation.SuppressLint
import
android.content.Context
import
android.util.AttributeSet
import
android.view.LayoutInflater
import
android.view.View
import
android.widget.Button
import
android.widget.FrameLayout
import
android.widget.ImageView
import
android.widget.TextView
import
androidx.annotation.LayoutRes
import
com.applovin.mediation.MaxAd
import
com.applovin.mediation.nativeAds.MaxNativeAdLoader
import
com.applovin.mediation.nativeAds.MaxNativeAdView
import
com.applovin.mediation.nativeAds.MaxNativeAdViewBinder
import
com.base.scanqr.R
import
com.google.android.gms.ads.nativead.NativeAd
import
com.google.android.gms.ads.nativead.NativeAdView
@SuppressLint
(
"ViewConstructor"
)
class
NativeParentView
(
context
:
Context
,
attrs
:
AttributeSet
?
=
null
)
:
FrameLayout
(
context
,
attrs
)
{
fun
setNativeAd
(
nativeAd
:
NativeAd
,
@LayoutRes
resource
:
Int
?
=
null
)
{
val
layout
=
resource
?:
R
.
layout
.
layout_admob_native_custom
val
adView
=
layout
.
let
{
LayoutInflater
.
from
(
context
).
inflate
(
it
,
null
)
}
as
NativeAdView
adView
.
mediaView
=
adView
.
findViewById
(
R
.
id
.
ad_media
)
adView
.
headlineView
=
adView
.
findViewById
(
R
.
id
.
ad_headline
)
adView
.
bodyView
=
adView
.
findViewById
(
R
.
id
.
ad_body
)
adView
.
callToActionView
=
adView
.
findViewById
(
R
.
id
.
ad_call_to_action
)
adView
.
iconView
=
adView
.
findViewById
(
R
.
id
.
ad_app_icon
)
(
adView
.
headlineView
as
TextView
?)
?.
text
=
nativeAd
.
headline
adView
.
mediaView
?.
mediaContent
=
nativeAd
.
mediaContent
if
(
nativeAd
.
body
==
null
)
{
adView
.
bodyView
?.
visibility
=
View
.
INVISIBLE
}
else
{
adView
.
bodyView
?.
visibility
=
View
.
VISIBLE
(
adView
.
bodyView
as
TextView
?)
?.
text
=
nativeAd
.
body
}
if
(
nativeAd
.
callToAction
==
null
)
{
adView
.
callToActionView
?.
visibility
=
View
.
INVISIBLE
}
else
{
adView
.
callToActionView
?.
visibility
=
View
.
VISIBLE
(
adView
.
callToActionView
as
Button
?)
?.
text
=
nativeAd
.
callToAction
}
if
(
nativeAd
.
icon
==
null
)
{
adView
.
iconView
?.
visibility
=
View
.
GONE
}
else
{
(
adView
.
iconView
as
ImageView
?)
?.
setImageDrawable
(
nativeAd
.
icon
?.
drawable
)
adView
.
iconView
?.
visibility
=
View
.
VISIBLE
}
adView
.
setNativeAd
(
nativeAd
)
setBackgroundResource
(
0
)
removeAllViews
()
addView
(
adView
)
}
fun
setNativeAd
(
nativeAdLoader
:
MaxNativeAdLoader
,
nativeAd
:
MaxAd
,
@LayoutRes
resource
:
Int
?
=
null
)
{
val
layout
=
resource
?:
R
.
layout
.
layout_max_native_custom
val
binder
:
MaxNativeAdViewBinder
=
MaxNativeAdViewBinder
.
Builder
(
layout
)
.
setTitleTextViewId
(
R
.
id
.
title_text_view
)
.
setBodyTextViewId
(
R
.
id
.
body_text_view
)
.
setAdvertiserTextViewId
(
R
.
id
.
advertiser_text_view
)
.
setIconImageViewId
(
R
.
id
.
icon_image_view
)
.
setMediaContentViewGroupId
(
R
.
id
.
media_view_container
)
.
setOptionsContentViewGroupId
(
R
.
id
.
options_view
)
.
setStarRatingContentViewGroupId
(
R
.
id
.
star_rating_view
)
.
setCallToActionButtonId
(
R
.
id
.
cta_button
)
.
build
()
val
adView
=
MaxNativeAdView
(
binder
,
context
)
nativeAdLoader
.
render
(
adView
,
nativeAd
)
setBackgroundResource
(
0
)
removeAllViews
()
addView
(
adView
)
}
}
app/src/main/java/com/base/scanqr/ads/admob/AdBannerMgr.kt
0 → 100644
View file @
e8ade6bb
package
com.base.scanqr.ads.admob
import
android.os.Bundle
import
android.view.ViewGroup
import
android.view.ViewTreeObserver
import
com.base.scanqr.GlobalConfig
import
com.base.scanqr.ads.AdsMgr
import
com.base.scanqr.ads.AdsType
import
com.base.scanqr.ads.LimitUtils
import
com.google.ads.mediation.admob.AdMobAdapter
import
com.google.android.gms.ads.AdListener
import
com.google.android.gms.ads.AdRequest
import
com.google.android.gms.ads.AdSize
import
com.google.android.gms.ads.AdView
import
com.google.android.gms.ads.LoadAdError
import
java.util.UUID
/**
*banner广告加载显示管理类
*/
class
AdBannerMgr
{
private
var
adView
:
AdView
?
=
null
private
var
listener
:
ViewTreeObserver
.
OnGlobalLayoutListener
?
=
null
fun
show
(
parent
:
ViewGroup
,
collapsible
:
Boolean
,
adClose
:
(()
->
Unit
)?
=
null
)
{
if
(!
AdsMgr
.
adsConfigBean
.
adSwitch
)
{
return
}
val
admobEvent
=
AdmobEvent
(
"banner"
,
"banner"
)
if
(!
LimitUtils
.
isAdShow
(
AdsType
.
BANNER
,
admobEvent
))
{
adView
=
null
return
}
parent
.
removeAllViews
()
adView
?.
destroy
()
adView
=
null
adView
=
AdView
(
parent
.
context
)
parent
.
addView
(
adView
)
adView
?.
onPaidEventListener
=
AdmobEvent
.
EventOnPaidEventListener
(
adView
)
listener
=
ViewTreeObserver
.
OnGlobalLayoutListener
{
val
screenPixelDensity
=
parent
.
context
.
resources
.
displayMetrics
.
density
val
adWidth
=
(
parent
.
width
/
screenPixelDensity
).
toInt
()
val
adSize
=
AdSize
.
getCurrentOrientationAnchoredAdaptiveBannerAdSize
(
parent
.
context
,
adWidth
)
adView
?.
adUnitId
=
GlobalConfig
.
ID_ADMOB_BANNER
adView
?.
setAdSize
(
adSize
)
loadAd
(
admobEvent
,
collapsible
,
adClose
)
parent
.
viewTreeObserver
.
removeOnGlobalLayoutListener
(
listener
)
}
parent
.
viewTreeObserver
.
addOnGlobalLayoutListener
(
listener
)
}
fun
loadAd
(
admobEvent
:
AdmobEvent
,
collapsible
:
Boolean
,
adClose
:
(()
->
Unit
)?)
{
val
build
=
AdRequest
.
Builder
()
if
(
collapsible
)
{
val
extras
=
Bundle
()
extras
.
putString
(
"collapsible"
,
"bottom"
)
extras
.
putString
(
"collapsible_request_id"
,
UUID
.
randomUUID
().
toString
())
build
.
addNetworkExtrasBundle
(
AdMobAdapter
::
class
.
java
,
extras
)
}
val
adRequest
=
build
.
build
()
adView
?.
adListener
=
object
:
AdListener
()
{
override
fun
onAdFailedToLoad
(
loadAdError
:
LoadAdError
)
{
super
.
onAdFailedToLoad
(
loadAdError
)
admobEvent
.
pullAd
(
loadAdError
.
responseInfo
,
loadAdError
)
}
override
fun
onAdLoaded
()
{
admobEvent
.
pullAd
(
adView
?.
responseInfo
)
}
override
fun
onAdOpened
()
{
}
override
fun
onAdClosed
()
{
super
.
onAdClosed
()
adClose
?.
invoke
()
}
}
adView
?.
loadAd
(
adRequest
)
}
}
\ No newline at end of file
app/src/main/java/com/base/scanqr/ads/admob/AdInsertMgr.kt
0 → 100644
View file @
e8ade6bb
package
com.base.scanqr.ads.admob
import
android.app.Activity
import
android.content.Context
import
com.base.scanqr.GlobalConfig
import
com.base.scanqr.ads.AdDialog.showAdPreparingDialog
import
com.base.scanqr.ads.AdEvent
import
com.base.scanqr.ads.AdsShowCallBack
import
com.base.scanqr.ads.AdsType
import
com.base.scanqr.ads.LimitUtils
import
com.base.scanqr.ads.adState
import
com.google.android.gms.ads.AdError
import
com.google.android.gms.ads.AdRequest
import
com.google.android.gms.ads.FullScreenContentCallback
import
com.google.android.gms.ads.LoadAdError
import
com.google.android.gms.ads.interstitial.InterstitialAd
import
com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback
import
java.lang.ref.WeakReference
/**
*插屏广告加载显示管理类
*/
class
AdInsertMgr
{
private
var
adState
=
adState
<
InterstitialAd
>()
private
var
showCallBack
:
AdsShowCallBack
?
=
null
fun
show
(
activity
:
Activity
,
isUnLimit
:
Boolean
,
adEvent
:
AdEvent
,
showCallBack
:
AdsShowCallBack
?)
{
if
(
activity
.
isFinishing
||
activity
.
isDestroyed
)
{
showCallBack
?.
failed
(
0
)
return
}
if
(
adState
.
showingAd
)
{
showCallBack
?.
failed
(
1
)
return
}
if
(
showCallBack
!=
null
)
{
this
.
showCallBack
=
showCallBack
adState
.
activityRef
=
WeakReference
(
activity
)
if
(
adState
.
adDialog
==
null
)
{
adState
.
adDialog
=
activity
.
showAdPreparingDialog
(
1
)
}
adEvent
.
adPrepareShow
()
}
if
(!
adState
.
loadingAd
)
{
if
(!
isUnLimit
)
{
if
(!
LimitUtils
.
isAdShow
(
AdsType
.
INSERT
,
adEvent
))
{
showCallBack
?.
failed
(
2
)
return
}
if
(
LimitUtils
.
isIntervalLimited
(
adState
.
lastShowTime
,
adEvent
))
{
showCallBack
?.
failed
(
3
)
return
}
}
if
(
adState
.
currentAd
==
null
)
{
loadAd
(
activity
,
isUnLimit
,
adEvent
)
return
}
if
(!
adAvailable
())
{
loadAd
(
activity
,
isUnLimit
,
adEvent
)
return
}
showReadyAd
(
adEvent
,
activity
)
}
}
private
fun
showReadyAd
(
adEvent
:
AdEvent
,
activity
:
Activity
)
{
adState
.
currentAd
?.
run
{
fullScreenContentCallback
=
object
:
FullScreenContentCallback
()
{
override
fun
onAdShowedFullScreenContent
()
{
super
.
onAdShowedFullScreenContent
()
adState
.
onAdDisplayed
()
showCallBack
?.
show
()
(
adEvent
as
AdmobEvent
).
showAd
(
responseInfo
,
activity
)
LimitUtils
.
addDisplayNum
()
}
override
fun
onAdFailedToShowFullScreenContent
(
adError
:
AdError
)
{
super
.
onAdFailedToShowFullScreenContent
(
adError
)
adState
.
onAdDisplayFailed
()
showCallBack
?.
googleFailed
()
showCallBack
=
null
adEvent
.
adShowError
(
adError
)
}
override
fun
onAdDismissedFullScreenContent
()
{
super
.
onAdDismissedFullScreenContent
()
adState
.
onAdHidden
()
showCallBack
?.
close
()
showCallBack
=
null
loadAd
(
activity
.
applicationContext
,
false
,
AdmobEvent
(
"interAd"
,
"preload"
))
}
override
fun
onAdClicked
()
{
super
.
onAdClicked
()
(
adEvent
as
AdmobEvent
).
clickAd
(
responseInfo
)
//计数
LimitUtils
.
addClickNum
()
}
}
show
(
activity
)
}
}
fun
loadAd
(
context
:
Context
,
isUnLimit
:
Boolean
,
adEvent
:
AdEvent
)
{
if
(!
isUnLimit
)
{
if
(!
LimitUtils
.
isAdShow
(
AdsType
.
INSERT
,
adEvent
))
{
this
.
showCallBack
?.
close
(
4
)
this
.
showCallBack
=
null
return
}
}
if
(!
adState
.
loadingAd
)
{
adState
.
loadingAd
=
true
adEvent
.
adPulStart
()
InterstitialAd
.
load
(
context
,
GlobalConfig
.
ID_ADMOB_INTER
,
AdRequest
.
Builder
().
build
(),
object
:
InterstitialAdLoadCallback
()
{
override
fun
onAdLoaded
(
ad
:
InterstitialAd
)
{
adState
.
onAdLoaded
(
ad
)
val
ac
=
adState
.
activityRef
?.
get
()
if
(
ac
!=
null
)
{
show
(
ac
,
isUnLimit
,
adEvent
,
null
)
}
(
adEvent
as
AdmobEvent
).
pullAd
(
ad
.
responseInfo
)
LimitUtils
.
addRequestNum
()
ad
.
onPaidEventListener
=
AdmobEvent
.
EventOnPaidEventListener
(
ad
)
}
override
fun
onAdFailedToLoad
(
loadAdError
:
LoadAdError
)
{
adState
.
onAdLoadFailed
()
(
adEvent
as
AdmobEvent
).
pullAd
(
loadAdError
.
responseInfo
,
loadAdError
)
showCallBack
?.
googleFailed
()
showCallBack
=
null
}
}
)
}
}
private
fun
adAvailable
()
=
((
System
.
currentTimeMillis
()
-
adState
.
lastLoadTime
)
/
1000
/
60
).
toInt
()
<
30
}
\ No newline at end of file
app/src/main/java/com/base/scanqr/ads/admob/AdNativeMgr.kt
0 → 100644
View file @
e8ade6bb
package
com.base.scanqr.ads.admob
import
com.base.scanqr.GlobalConfig
import
com.base.scanqr.ads.AdsType
import
com.base.scanqr.ads.LimitUtils
import
com.base.scanqr.ads.NativeParentView
import
com.google.android.gms.ads.AdListener
import
com.google.android.gms.ads.AdLoader
import
com.google.android.gms.ads.AdRequest
import
com.google.android.gms.ads.LoadAdError
import
com.google.android.gms.ads.nativead.NativeAd
import
com.google.android.gms.ads.nativead.NativeAdOptions
import
java.util.concurrent.ConcurrentLinkedDeque
/**
*原生广告加载显示管理类
*/
class
AdNativeMgr
{
/**
* 上一次的缓存成功时间
*/
protected
var
lastTime
:
Long
=
0
/**
* 原生广告缓存队列
*/
private
val
cacheItems
=
ConcurrentLinkedDeque
<
NativeAd
>()
private
fun
loadAd
(
admobEvent
:
AdmobEvent
,
parent
:
NativeParentView
,
layout
:
Int
)
{
admobEvent
.
adPulStart
()
if
(!
LimitUtils
.
isAdShow
(
AdsType
.
NATIVE
,
admobEvent
))
return
var
currentNativeAd
:
NativeAd
?
=
null
val
adLoader
=
AdLoader
.
Builder
(
parent
.
context
,
GlobalConfig
.
ID_ADMOB_NATIVE
).
forNativeAd
{
nativeAd
->
currentNativeAd
=
nativeAd
cacheItems
.
offer
(
nativeAd
)
lastTime
=
System
.
currentTimeMillis
()
nativeAd
.
setOnPaidEventListener
(
AdmobEvent
.
EventOnPaidEventListener
(
nativeAd
))
admobEvent
.
pullAd
(
nativeAd
.
responseInfo
)
show
(
admobEvent
,
parent
,
layout
)
}.
withAdListener
(
object
:
AdListener
()
{
override
fun
onAdFailedToLoad
(
error
:
LoadAdError
)
{
admobEvent
.
pullAd
(
error
.
responseInfo
,
error
)
}
override
fun
onAdClicked
()
{
super
.
onAdClicked
()
admobEvent
.
clickAd
(
currentNativeAd
?.
responseInfo
)
}
override
fun
onAdClosed
()
{
super
.
onAdClosed
()
}
}).
withNativeAdOptions
(
NativeAdOptions
.
Builder
()
.
build
()
).
build
()
adLoader
.
loadAds
(
AdRequest
.
Builder
().
build
(),
1
)
}
fun
show
(
admobEvent
:
AdmobEvent
,
parent
:
NativeParentView
,
layout
:
Int
,
nativeCallBack
:
((
Any
?)
->
Unit
)?
=
null
)
{
admobEvent
.
adPrepareShow
()
if
(!
LimitUtils
.
isAdShow
(
AdsType
.
NATIVE
,
admobEvent
))
{
cacheItems
.
clear
()
return
}
val
nativeAd
=
cacheItems
.
peek
()
if
(
nativeAd
==
null
||
!
adAvailable
())
{
//缓存过期了就清空
cacheItems
.
clear
()
loadAd
(
admobEvent
,
parent
,
layout
)
return
}
nativeCallBack
?.
invoke
(
nativeAd
)
parent
.
setNativeAd
(
nativeAd
,
layout
)
admobEvent
.
showAd
(
nativeAd
.
responseInfo
)
}
private
fun
adAvailable
():
Boolean
{
return
((
System
.
currentTimeMillis
()
-
lastTime
)
/
1000
/
60
).
toInt
()
<
30
}
}
\ No newline at end of file
app/src/main/java/com/base/scanqr/ads/admob/AdOpenMgr.kt
0 → 100644
View file @
e8ade6bb
package
com.base.scanqr.ads.admob
import
android.app.Activity
import
android.content.Context
import
com.base.scanqr.GlobalConfig
import
com.base.scanqr.ads.AdEvent
import
com.base.scanqr.ads.AdsShowCallBack
import
com.base.scanqr.ads.AdsType
import
com.base.scanqr.ads.LimitUtils
import
com.base.scanqr.ads.adState
import
com.google.android.gms.ads.AdError
import
com.google.android.gms.ads.AdRequest
import
com.google.android.gms.ads.FullScreenContentCallback
import
com.google.android.gms.ads.LoadAdError
import
com.google.android.gms.ads.appopen.AppOpenAd
import
java.lang.ref.WeakReference
/**
* 开屏广告加载显示管理类
*/
class
AdOpenMgr
{
private
val
adState
=
adState
<
AppOpenAd
>()
private
var
showCallBack
:
AdsShowCallBack
?
=
null
fun
show
(
activity
:
Activity
,
isUnLimit
:
Boolean
,
adEvent
:
AdEvent
,
showCallBack
:
AdsShowCallBack
?)
{
if
(
activity
.
isFinishing
||
activity
.
isDestroyed
)
{
return
}
if
(
adState
.
showingAd
)
{
showCallBack
?.
failed
()
adEvent
.
adShowError
(
"showingAd"
)
return
}
if
(
showCallBack
!=
null
)
{
this
.
showCallBack
=
showCallBack
adState
.
activityRef
=
WeakReference
(
activity
)
adEvent
.
adPrepareShow
()
}
if
(!
adState
.
loadingAd
)
{
if
(!
isUnLimit
)
{
if
(!
LimitUtils
.
isAdShow
(
AdsType
.
OPEN
,
adEvent
))
{
showCallBack
?.
failed
()
return
}
if
(
LimitUtils
.
isIntervalLimited
(
adState
.
lastShowTime
,
adEvent
))
{
showCallBack
?.
failed
()
return
}
}
if
(!
adAvailable
()
||
adState
.
currentAd
==
null
)
{
loadAd
(
activity
,
isUnLimit
,
adEvent
)
return
}
showReadyAd
(
adEvent
,
activity
)
}
}
private
fun
showReadyAd
(
adEvent
:
AdEvent
,
activity
:
Activity
)
{
adState
.
currentAd
?.
run
{
fullScreenContentCallback
=
object
:
FullScreenContentCallback
()
{
override
fun
onAdShowedFullScreenContent
()
{
showCallBack
?.
show
()
(
adEvent
as
AdmobEvent
).
showAd
(
this
@run
.
responseInfo
,
activity
)
adState
.
onAdDisplayed
()
//计数
LimitUtils
.
addDisplayNum
()
}
override
fun
onAdFailedToShowFullScreenContent
(
adError
:
AdError
)
{
super
.
onAdFailedToShowFullScreenContent
(
adError
)
showCallBack
?.
googleFailed
()
showCallBack
=
null
adState
.
onAdDisplayed
()
(
adEvent
as
AdmobEvent
).
adShowError
(
adError
)
}
override
fun
onAdDismissedFullScreenContent
()
{
super
.
onAdDismissedFullScreenContent
()
showCallBack
?.
close
()
showCallBack
=
null
adState
.
onAdHidden
()
loadAd
(
activity
.
applicationContext
,
false
,
AdmobEvent
(
"openAd"
,
"preload"
))
}
override
fun
onAdClicked
()
{
(
adEvent
as
AdmobEvent
).
clickAd
(
this
@run
.
responseInfo
)
//计数
LimitUtils
.
addClickNum
()
}
}
show
(
activity
)
}
}
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
()
AppOpenAd
.
load
(
context
,
GlobalConfig
.
ID_ADMOB_OPEN
,
AdRequest
.
Builder
().
build
(),
object
:
AppOpenAd
.
AppOpenAdLoadCallback
()
{
override
fun
onAdLoaded
(
appOpenAd
:
AppOpenAd
)
{
adState
.
onAdLoaded
(
appOpenAd
)
val
ac
=
adState
.
activityRef
?.
get
()
if
(
ac
!=
null
)
{
show
(
ac
,
isUnLimit
,
adEvent
,
null
)
}
(
adEvent
as
AdmobEvent
).
pullAd
(
appOpenAd
.
responseInfo
)
appOpenAd
.
onPaidEventListener
=
AdmobEvent
.
EventOnPaidEventListener
(
appOpenAd
)
LimitUtils
.
addRequestNum
()
}
override
fun
onAdFailedToLoad
(
loadAdError
:
LoadAdError
)
{
showCallBack
?.
googleFailed
()
showCallBack
=
null
adState
.
onAdLoadFailed
()
(
adEvent
as
AdmobEvent
).
pullAd
(
loadAdError
.
responseInfo
,
loadAdError
)
}
}
)
}
}
private
fun
adAvailable
()
=
((
System
.
currentTimeMillis
()
-
adState
.
lastLoadTime
)
/
1000
/
60
).
toInt
()
<
30
}
\ No newline at end of file
app/src/main/java/com/base/scanqr/ads/admob/AdmobEvent.kt
0 → 100644
View file @
e8ade6bb
This diff is collapsed.
Click to expand it.
app/src/main/java/com/base/scanqr/ads/applovin/AdMaxEvent.kt
0 → 100644
View file @
e8ade6bb
package
com.base.scanqr.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.base.scanqr.MyApplication
import
com.base.scanqr.ads.AdEvent
import
com.base.scanqr.ads.taichiPref
import
com.base.scanqr.ads.taichiSharedPreferencesEditor
import
com.base.scanqr.helper.EventUtils
import
com.base.scanqr.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/base/scanqr/ads/applovin/MaxInsertMgr.kt
0 → 100644
View file @
e8ade6bb
package
com.base.scanqr.ads.applovin
import
android.app.Activity
import
android.content.Context
import
com.applovin.mediation.MaxAd
import
com.applovin.mediation.MaxAdListener
import
com.applovin.mediation.MaxError
import
com.applovin.mediation.ads.MaxInterstitialAd
import
com.base.scanqr.GlobalConfig
import
com.base.scanqr.ads.AdDialog.showAdPreparingDialog
import
com.base.scanqr.ads.AdEvent
import
com.base.scanqr.ads.AdsShowCallBack
import
com.base.scanqr.ads.AdsType
import
com.base.scanqr.ads.LimitUtils
import
com.base.scanqr.ads.adState
import
java.lang.ref.WeakReference
/**
*插屏广告加载显示管理类
*/
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
(
adState
.
showingAd
)
{
showCallBack
?.
failed
(
2
)
return
}
if
(
showCallBack
!=
null
)
{
adState
.
activityRef
=
WeakReference
(
activity
)
this
.
showCallBack
=
showCallBack
if
(
adState
.
adDialog
==
null
)
{
adState
.
adDialog
=
activity
.
showAdPreparingDialog
(
2
)
}
adEvent
.
adPrepareShow
()
}
if
(!
adState
.
loadingAd
)
{
if
(!
isUnLimit
)
{
if
(!
LimitUtils
.
isAdShow
(
AdsType
.
INSERT
,
adEvent
))
{
showCallBack
?.
failed
(
3
)
return
}
if
(
LimitUtils
.
isIntervalLimited
(
adState
.
lastShowTime
,
adEvent
))
{
showCallBack
?.
failed
(
4
)
return
}
}
if
(!
adAvailable
()
||
adState
.
currentAd
==
null
)
{
loadAd
(
activity
,
isUnLimit
,
adEvent
)
return
}
if
(
adState
.
currentAd
?.
isReady
==
false
)
{
loadAd
(
activity
,
isUnLimit
,
adEvent
)
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
?.
googleFailed
()
showCallBack
=
null
(
adEvent
as
AdMaxEvent
).
adShowError
(
error
)
}
override
fun
onAdHidden
(
p0
:
MaxAd
)
{
adState
.
onAdHidden
()
showCallBack
?.
close
()
loadAd
(
activity
.
applicationContext
,
false
,
AdMaxEvent
(
"interAd"
,
"preload"
))
}
override
fun
onAdClicked
(
ad
:
MaxAd
)
{
(
adEvent
as
AdMaxEvent
).
clickAd
(
ad
)
//计数
LimitUtils
.
addClickNum
()
}
})
setRevenueListener
(
AdMaxEvent
.
EventOnPaidEventListener
())
showAd
(
activity
)
}
}
fun
loadAd
(
context
:
Context
,
isUnLimit
:
Boolean
,
adEvent
:
AdEvent
,
)
{
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
,
context
)
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
)
val
ac
=
adState
.
activityRef
?.
get
()
if
(
ac
!=
null
)
{
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
?.
googleFailed
(
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/base/scanqr/ads/applovin/MaxNativeMgr.kt
0 → 100644
View file @
e8ade6bb
package
com.base.scanqr.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.base.scanqr.GlobalConfig
import
com.base.scanqr.ads.AdsType
import
com.base.scanqr.ads.LimitUtils
import
com.base.scanqr.ads.NativeParentView
import
com.base.scanqr.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/base/scanqr/ads/applovin/MaxOpenMgr.kt
0 → 100644
View file @
e8ade6bb
package
com.base.scanqr.ads.applovin
import
android.app.Activity
import
android.content.Context
import
com.applovin.mediation.MaxAd
import
com.applovin.mediation.MaxAdListener
import
com.applovin.mediation.MaxError
import
com.applovin.mediation.ads.MaxAppOpenAd
import
com.base.scanqr.GlobalConfig
import
com.base.scanqr.ads.AdEvent
import
com.base.scanqr.ads.AdsShowCallBack
import
com.base.scanqr.ads.AdsType
import
com.base.scanqr.ads.LimitUtils
import
com.base.scanqr.ads.adState
import
java.lang.ref.WeakReference
/**
* 开屏广告加载显示管理类
*/
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
(
adState
.
showingAd
)
{
showCallBack
?.
failed
()
adEvent
.
adShowError
(
"showingAd"
)
return
}
if
(
showCallBack
!=
null
)
{
this
.
showCallBack
=
showCallBack
adState
.
activityRef
=
WeakReference
(
activity
)
adEvent
.
adPrepareShow
()
}
if
(!
adState
.
loadingAd
)
{
if
(!
isUnLimit
)
{
if
(!
LimitUtils
.
isAdShow
(
AdsType
.
OPEN
,
adEvent
))
{
showCallBack
?.
failed
()
return
}
if
(
LimitUtils
.
isIntervalLimited
(
adState
.
lastShowTime
,
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
?.
googleFailed
()
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
?.
googleFailed
()
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/base/scanqr/bean/ConstObject.kt
View file @
e8ade6bb
...
@@ -4,6 +4,15 @@ import com.base.scanqr.utils.AppPreferences
...
@@ -4,6 +4,15 @@ import com.base.scanqr.utils.AppPreferences
import
java.util.Locale
import
java.util.Locale
object
ConstObject
{
object
ConstObject
{
var
mainStartTimes
=
0
get
()
{
return
AppPreferences
.
getInstance
().
getInt
(
"mainStartTimes"
,
field
)
}
set
(
value
)
{
field
=
value
AppPreferences
.
getInstance
().
put
(
"mainStartTimes"
,
value
,
true
)
}
var
ifAgreePrivacy
=
true
var
ifAgreePrivacy
=
true
get
()
{
get
()
{
...
...
app/src/main/java/com/base/scanqr/bean/config/AdConfigBean.kt
0 → 100644
View file @
e8ade6bb
package
com.base.scanqr.bean.config
class
AdConfigBean
(
var
adSwitch
:
Boolean
=
true
,
//true 走admob,false走max
var
numDisplayLimit
:
Int
=
-
1
,
var
numRequestLimit
:
Int
=
-
1
,
var
numClickLimit
:
Int
=
-
1
,
var
timeInterval
:
Int
=
1
,
var
openAdLoading
:
Int
=
15
,
var
functionBackShowAd
:
Boolean
=
true
,
var
functionInShowAd
:
Boolean
=
true
,
)
\ No newline at end of file
app/src/main/java/com/base/scanqr/bean/config/ConfigBean.kt
0 → 100644
View file @
e8ade6bb
package
com.base.appzxhy.bean.config
import
com.base.scanqr.bean.config.AdConfigBean
import
com.base.scanqr.bean.config.PopupConfigBean
/**
* 后台配置
*/
data class
ConfigBean
(
var
isInBlackList
:
Boolean
=
false
,
val
ut
:
Int
=
0
,
val
adConfigBean
:
AdConfigBean
=
AdConfigBean
(),
val
popupConfigBean
:
PopupConfigBean
=
PopupConfigBean
(),
)
{
companion
object
{
var
configBean
:
ConfigBean
=
ConfigBean
()
}
}
\ No newline at end of file
app/src/main/java/com/base/scanqr/bean/config/PopupConfigBean.kt
0 → 100644
View file @
e8ade6bb
package
com.base.scanqr.bean.config
class
PopupConfigBean
(
var
popupStatus
:
Boolean
=
true
,
var
popupCount
:
Int
=
24
,
var
popupStart
:
Int
=
0
,
var
popupEnd
:
Int
=
24
,
var
popupInterval
:
Int
=
1
,
var
popupTimerInterval
:
Int
=
1
,
var
popupFcmInterval
:
Int
=
1
,
var
popupHoverStatus
:
Boolean
=
true
,
var
popupHoverCount
:
Int
=
5
,
var
popupHoverDelay
:
Int
=
5000
,
//定时器
var
timerS
:
Boolean
=
true
,
var
timerDelay
:
Int
=
1
,
var
timerInterval
:
Int
=
1
,
//解锁
var
screenS
:
Boolean
=
true
,
var
popupScreenCount
:
Int
=
20
,
var
popupScreenInterval
:
Int
=
1
,
//电量
var
batteryS
:
Boolean
=
true
,
var
popupBatteryValue
:
Int
=
20
,
var
popupBatteryInterval
:
Int
=
1
,
//安装卸载
var
packageS
:
Boolean
=
true
,
var
popupPackageCount
:
Int
=
20
,
var
popupPackageInterval
:
Int
=
1
)
\ No newline at end of file
app/src/main/java/com/base/scanqr/fcm/FCMManager.kt
0 → 100644
View file @
e8ade6bb
package
com.base.scanqr.fcm
import
android.content.Context
import
android.util.Log
import
com.base.scanqr.helper.EventUtils.event
import
com.base.scanqr.utils.AppPreferences
import
com.base.scanqr.utils.LogEx
import
com.google.android.gms.tasks.OnCompleteListener
import
com.google.android.gms.tasks.Task
import
com.google.firebase.FirebaseApp
import
com.google.firebase.messaging.FirebaseMessaging
import
org.json.JSONObject
object
FCMManager
{
fun
initFirebase
(
context
:
Context
?)
{
FirebaseApp
.
initializeApp
(
context
!!
)
LogEx
.
logDebug
(
"initFirebase"
,
"initFirebase"
)
getToken
()
}
fun
subscribeToTopic
(
topic
:
String
)
{
Log
.
e
(
"FCMUtil"
,
"subscribeToTopic"
)
FirebaseMessaging
.
getInstance
().
subscribeToTopic
(
topic
)
.
addOnCompleteListener
{
task
->
if
(
task
.
isSuccessful
)
{
getToken
()
Log
.
e
(
"FCMUtil"
,
"isSuccessful"
)
event
(
"FCM_Topic_$topic"
,
null
,
null
)
}
else
{
event
(
"FCM_Error"
,
"subscribeToTopic task.isSuccessful=${task.isSuccessful} "
,
null
)
}
}
}
fun
unsubscribeFromTopic
(
topic
:
String
?)
{
FirebaseMessaging
.
getInstance
().
unsubscribeFromTopic
(
topic
!!
)
.
addOnCompleteListener
{
task
->
if
(
task
.
isSuccessful
)
{
}
else
{
}
}
}
/**
* 有vpn有google商店才能获取
*/
private
fun
getToken
()
{
FirebaseMessaging
.
getInstance
().
token
.
addOnCompleteListener
(
object
:
OnCompleteListener
<
String
>
{
override
fun
onComplete
(
task
:
Task
<
String
>)
{
LogEx
.
logDebug
(
"FCM"
,
"onComplete ${task.isSuccessful}"
)
if
(!
task
.
isSuccessful
)
{
Log
.
e
(
"FCM"
,
"Fetching FCM registration token failed"
,
task
.
exception
)
return
}
// Get new FCM registration token
val
token
:
String
=
task
.
result
LogEx
.
logDebug
(
"FCM"
,
"token=$token"
)
val
json
=
JSONObject
()
json
.
put
(
"token"
,
token
)
event
(
"fcm_message_received"
,
ext
=
json
)
AppPreferences
.
getInstance
().
put
(
"token"
,
token
)
// Handle new token
LogEx
.
logDebug
(
"FCM"
,
"FCM Registration Token: $token"
)
}
})
}
}
app/src/main/java/com/base/scanqr/helper/AppConfig.kt
deleted
100644 → 0
View file @
fe134c80
package
com.base.scanqr.helper
object
AppConfig
{
const
val
privacyPolicy
:
String
=
""
const
val
termService
:
String
=
""
// 正式包名
const
val
packageName
=
"com.loactation.alibabab.ccccaa"
// 域名
const
val
eventUrl
=
"https://rp.gamexzonerk.xyz"
const
val
apiUrl
=
"https://api.gamexzonerk.xyz"
val
noLoadingActivities
=
listOf
(
"full"
,
// 过滤全屏广告
"adActivity"
,
"AdActivity"
,
"AppLovinFullscreenActivity"
,
// SplashActivity::class.java.simpleName,
// 返回前台时不跳转启动页的 activity
)
}
\ No newline at end of file
app/src/main/java/com/base/scanqr/helper/EventUtils.kt
View file @
e8ade6bb
...
@@ -2,6 +2,7 @@ package com.base.scanqr.helper
...
@@ -2,6 +2,7 @@ package com.base.scanqr.helper
import
android.os.Build
import
android.os.Build
import
com.base.scanqr.BuildConfig
import
com.base.scanqr.BuildConfig
import
com.base.scanqr.GlobalConfig
import
com.base.scanqr.helper.ReportUtils.doPost
import
com.base.scanqr.helper.ReportUtils.doPost
import
com.base.scanqr.utils.AppPreferences
import
com.base.scanqr.utils.AppPreferences
import
com.base.scanqr.utils.LogEx
import
com.base.scanqr.utils.LogEx
...
@@ -34,7 +35,7 @@ object EventUtils {
...
@@ -34,7 +35,7 @@ object EventUtils {
Thread
{
Thread
{
var
paramJson
:
String
?
=
""
var
paramJson
:
String
?
=
""
try
{
try
{
val
pkg
=
AppConfig
.
packageName
val
pkg
=
GlobalConfig
.
PACKAGE_NAME
val
s
=
JSONObject
()
val
s
=
JSONObject
()
.
put
(
"action"
,
key
)
.
put
(
"action"
,
key
)
.
put
(
"value"
,
value
)
.
put
(
"value"
,
value
)
...
@@ -72,9 +73,9 @@ object EventUtils {
...
@@ -72,9 +73,9 @@ object EventUtils {
}
}
private
val
url
by
lazy
{
private
val
url
by
lazy
{
val
pkg
=
AppConfig
.
packageName
val
pkg
=
GlobalConfig
.
PACKAGE_NAME
val
url
=
StringBuilder
(
val
url
=
StringBuilder
(
"${
AppConfig.eventUrl
}/${
"${
GlobalConfig.URL_EVENT
}/${
pkg
.
filter
{
it
.
isLowerCase
()
}.
substring
(
4
,
9
)
pkg
.
filter
{
it
.
isLowerCase
()
}.
substring
(
4
,
9
)
}
sp
"
}
sp
"
)
)
...
...
app/src/main/java/com/base/scanqr/qr/CameraUtils.kt
View file @
e8ade6bb
...
@@ -11,7 +11,6 @@ import androidx.camera.lifecycle.ProcessCameraProvider
...
@@ -11,7 +11,6 @@ import androidx.camera.lifecycle.ProcessCameraProvider
import
androidx.camera.view.PreviewView
import
androidx.camera.view.PreviewView
import
androidx.core.content.ContextCompat
import
androidx.core.content.ContextCompat
import
androidx.lifecycle.LiveData
import
androidx.lifecycle.LiveData
import
com.base.scanqr.utils.LogEx
import
java.util.concurrent.ExecutorService
import
java.util.concurrent.ExecutorService
import
java.util.concurrent.Executors
import
java.util.concurrent.Executors
import
kotlin.math.abs
import
kotlin.math.abs
...
...
app/src/main/java/com/base/scanqr/ui/main/MainActivity.kt
View file @
e8ade6bb
...
@@ -12,10 +12,13 @@ import com.base.scanqr.bean.HomeTabUIBean
...
@@ -12,10 +12,13 @@ import com.base.scanqr.bean.HomeTabUIBean
import
com.base.scanqr.databinding.ActivityMainBinding
import
com.base.scanqr.databinding.ActivityMainBinding
import
com.base.scanqr.databinding.ItemHomeTabBinding
import
com.base.scanqr.databinding.ItemHomeTabBinding
import
com.base.scanqr.qr.CameraUtils
import
com.base.scanqr.qr.CameraUtils
import
com.base.scanqr.ui.widget.NotificationDialog.showNotificationTurnOn
import
com.base.scanqr.utils.LogEx
import
com.base.scanqr.utils.LogEx
import
com.base.scanqr.utils.PermissionUtils.areNotificationsEnabled
import
com.google.android.material.tabs.TabLayout
import
com.google.android.material.tabs.TabLayout
import
com.google.android.material.tabs.TabLayout.OnTabSelectedListener
import
com.google.android.material.tabs.TabLayout.OnTabSelectedListener
import
com.gyf.immersionbar.ktx.immersionBar
import
com.gyf.immersionbar.ktx.immersionBar
import
java.util.concurrent.atomic.AtomicBoolean
class
MainActivity
:
BaseActivity
<
ActivityMainBinding
>(
ActivityMainBinding
::
inflate
)
{
class
MainActivity
:
BaseActivity
<
ActivityMainBinding
>(
ActivityMainBinding
::
inflate
)
{
...
@@ -32,9 +35,20 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
...
@@ -32,9 +35,20 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
)
)
}
}
private
var
bannerShowed
=
AtomicBoolean
(
false
)
override
fun
onResumeOneShoot
()
{
override
fun
onResumeOneShoot
()
{
super
.
onResumeOneShoot
()
super
.
onResumeOneShoot
()
changeLanguage
()
val
flag
=
changeLanguage
()
if
(
flag
)
return
if
(!
bannerShowed
.
get
())
{
bannerShowed
.
set
(
true
)
}
else
{
if
(!
areNotificationsEnabled
())
{
showNotificationTurnOn
(
launcher
)
}
}
}
}
override
fun
initView
()
{
override
fun
initView
()
{
...
...
app/src/main/java/com/base/scanqr/ui/widget/NotificationDialog.kt
0 → 100644
View file @
e8ade6bb
package
com.base.scanqr.ui.widget
import
android.annotation.SuppressLint
import
android.app.AlertDialog
import
android.content.Context
import
android.content.Intent
import
android.os.Build
import
android.provider.Settings
import
android.view.Gravity
import
android.view.LayoutInflater
import
com.base.scanqr.R
import
com.base.scanqr.databinding.DialogNotificationTurnOnBinding
import
com.base.scanqr.utils.ActivityLauncher
object
NotificationDialog
{
@SuppressLint
(
"SetTextI18n"
)
fun
Context
.
showNotificationTurnOn
(
launcher
:
ActivityLauncher
)
{
val
dialog
=
AlertDialog
.
Builder
(
this
).
create
()
val
binding
=
DialogNotificationTurnOnBinding
.
inflate
(
LayoutInflater
.
from
(
this
))
dialog
.
setView
(
binding
.
root
)
dialog
.
setCanceledOnTouchOutside
(
true
)
dialog
.
show
()
val
params
=
dialog
.
window
?.
attributes
// params?.width = resources.getDimensionPixelOffset(R.dimen.dp_320)
// params?.height = LinearLayout.LayoutParams.WRAP_CONTENT
params
?.
gravity
=
Gravity
.
BOTTOM
// params?.y = 50
dialog
.
window
?.
attributes
=
params
dialog
.
window
?.
setBackgroundDrawableResource
(
android
.
R
.
color
.
transparent
)
val
appName
=
resources
.
getString
(
R
.
string
.
app_name
)
binding
.
tvTip
.
text
=
"Never miss important $appName notification reminders"
binding
.
ivClose
.
setOnClickListener
{
dialog
.
dismiss
()
}
binding
.
tvTurnOn
.
setOnClickListener
{
dialog
.
dismiss
()
val
intent
=
Intent
()
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
O
)
{
intent
.
action
=
Settings
.
ACTION_APP_NOTIFICATION_SETTINGS
intent
.
putExtra
(
Settings
.
EXTRA_APP_PACKAGE
,
this
.
packageName
)
}
else
{
intent
.
action
=
"android.settings.APP_NOTIFICATION_SETTINGS"
intent
.
putExtra
(
"app_package"
,
this
.
packageName
)
}
launcher
.
launch
(
intent
)
}
}
}
\ No newline at end of file
app/src/main/res/drawable/bg_6379e6_35.xml
0 → 100644
View file @
e8ade6bb
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<solid
android:color=
"#6379E6"
/>
<corners
android:radius=
"35dp"
/>
</shape>
\ No newline at end of file
app/src/main/res/drawable/bg_ff8a00_10.xml
0 → 100644
View file @
e8ade6bb
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<solid
android:color=
"#ff8a00"
/>
<corners
android:radius=
"10dp"
/>
</shape>
\ No newline at end of file
app/src/main/res/layout/dialog_ad_preparing.xml
0 → 100644
View file @
e8ade6bb
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"180dp"
android:layout_height=
"136dp"
android:layout_margin=
"5dp"
app:cardCornerRadius=
"25dp"
app:cardElevation=
"0dp"
>
<LinearLayout
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:orientation=
"vertical"
tools:ignore=
"UseCompoundDrawables"
>
<ImageView
android:id=
"@+id/iv"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_horizontal"
android:layout_marginTop=
"23dp"
android:src=
"@mipmap/jiazai_ad"
tools:ignore=
"ContentDescription"
/>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_horizontal"
android:layout_marginTop=
"18dp"
android:layout_marginBottom=
"22dp"
android:includeFontPadding=
"false"
android:text=
"@string/preparing_advertisement"
android:textColor=
"@color/black"
android:textSize=
"13sp"
tools:ignore=
"HardcodedText"
/>
</LinearLayout>
</androidx.cardview.widget.CardView>
\ No newline at end of file
app/src/main/res/layout/dialog_notification_turn_on.xml
0 → 100644
View file @
e8ade6bb
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
>
<ImageView
android:layout_width=
"match_parent"
android:layout_height=
"342dp"
android:background=
"@mipmap/img_tongzhi_pop_bj"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
tools:ignore=
"ContentDescription"
/>
<ImageView
android:id=
"@+id/iv_close"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_margin=
"25dp"
android:src=
"@mipmap/icon_close"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
tools:ignore=
"ContentDescription"
/>
<LinearLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:orientation=
"vertical"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_horizontal"
android:layout_marginBottom=
"8dp"
android:text=
"@string/turn_on_notification"
android:textColor=
"#1A1A1A"
android:textSize=
"22sp"
android:textStyle=
"bold"
/>
<TextView
android:id=
"@+id/tv_tip"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_horizontal"
android:layout_marginHorizontal=
"40dp"
android:layout_marginBottom=
"20dp"
android:gravity=
"center"
android:textColor=
"#666666"
android:textSize=
"16sp"
/>
<TextView
android:id=
"@+id/tv_turn_on"
android:layout_width=
"259dp"
android:layout_height=
"48dp"
android:layout_gravity=
"center_horizontal"
android:layout_marginBottom=
"40dp"
android:background=
"@drawable/bg_6379e6_35"
android:gravity=
"center"
android:text=
"@string/turn_on"
android:textColor=
"@color/white"
android:textSize=
"20sp"
/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
app/src/main/res/layout/layout_admob_native_custom.xml
0 → 100644
View file @
e8ade6bb
<com.google.android.gms.ads.nativead.NativeAdView
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_margin=
"10dp"
>
<LinearLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:background=
"#f2f2f2"
android:baselineAligned=
"false"
>
<com.google.android.gms.ads.nativead.MediaView
android:id=
"@+id/ad_media"
android:layout_width=
"91dp"
android:layout_height=
"91dp"
android:layout_gravity=
"center_vertical"
android:layout_marginStart=
"5dp"
/>
<LinearLayout
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_vertical"
android:layout_marginHorizontal=
"8dp"
android:layout_weight=
"1"
android:orientation=
"vertical"
>
<TextView
android:id=
"@+id/ad_headline"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:ellipsize=
"end"
android:maxLines=
"2"
android:textColor=
"@color/black"
android:textSize=
"14sp"
android:textStyle=
"bold"
/>
<LinearLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:orientation=
"horizontal"
>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_vertical"
android:background=
"#FF923E"
android:padding=
"2dp"
android:text=
"Ad"
android:textColor=
"@color/white"
android:textSize=
"12sp"
tools:ignore=
"HardcodedText,TextContrastCheck,TextContrastCheck"
/>
<TextView
android:id=
"@+id/ad_body"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"8dp"
android:layout_marginEnd=
"10dp"
android:ellipsize=
"end"
android:maxLines=
"2"
android:textColor=
"@color/black"
android:textSize=
"12sp"
/>
</LinearLayout>
<LinearLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:paddingVertical=
"5dp"
>
<ImageView
android:id=
"@+id/ad_app_icon"
android:layout_width=
"30dp"
android:layout_height=
"30dp"
android:layout_gravity=
"center_vertical"
tools:ignore=
"ContentDescription"
/>
<androidx.appcompat.widget.AppCompatButton
android:id=
"@+id/ad_call_to_action"
android:layout_width=
"match_parent"
android:layout_height=
"26dp"
android:layout_gravity=
"center_vertical"
android:layout_marginHorizontal=
"12dp"
android:background=
"@drawable/bg_ff8a00_10"
android:gravity=
"center"
android:textColor=
"@color/white"
android:textSize=
"15sp"
tools:ignore=
"SpeakableTextPresentCheck,TouchTargetSizeCheck,VisualLintButtonSize"
/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</com.google.android.gms.ads.nativead.NativeAdView>
\ No newline at end of file
app/src/main/res/layout/layout_max_native_custom.xml
0 → 100644
View file @
e8ade6bb
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:maxHeight=
"300dp"
android:padding=
"8dp"
>
<ImageView
android:id=
"@+id/icon_image_view"
android:layout_width=
"50dp"
android:layout_height=
"50dp"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
tools:src=
"@mipmap/ic_launcher"
/>
<TextView
android:id=
"@+id/text_view"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"8dp"
android:background=
"@android:color/holo_green_dark"
android:padding=
"2dp"
android:text=
"Ad"
android:textAppearance=
"@style/TextAppearance.AppCompat.Body2"
android:textColor=
"@android:color/white"
app:layout_constraintBottom_toBottomOf=
"@+id/title_text_view"
app:layout_constraintStart_toEndOf=
"@+id/icon_image_view"
app:layout_constraintTop_toTopOf=
"@+id/title_text_view"
tools:ignore=
"RtlHardcoded,TextContrastCheck"
/>
<FrameLayout
android:id=
"@+id/options_view"
android:layout_width=
"25dp"
android:layout_height=
"25dp"
android:layout_marginBottom=
"8dp"
android:orientation=
"horizontal"
app:layout_constraintBottom_toTopOf=
"@+id/advertiser_text_view"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintHorizontal_bias=
"1.0"
app:layout_constraintStart_toEndOf=
"@+id/title_text_view"
app:layout_constraintTop_toTopOf=
"@+id/icon_image_view"
/>
<TextView
android:id=
"@+id/title_text_view"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"8dp"
android:layout_marginLeft=
"8dp"
android:textAppearance=
"@style/TextAppearance.AppCompat.Title"
app:layout_constraintStart_toEndOf=
"@+id/text_view"
app:layout_constraintTop_toTopOf=
"parent"
tools:text=
"Title"
/>
<TextView
android:id=
"@+id/advertiser_text_view"
android:layout_width=
"wrap_content"
android:layout_height=
"8dp"
android:layout_marginStart=
"8dp"
android:textAppearance=
"@style/TextAppearance.AppCompat.Body1"
app:layout_constraintBottom_toBottomOf=
"@+id/icon_image_view"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintHorizontal_bias=
"0.0"
app:layout_constraintStart_toEndOf=
"@+id/icon_image_view"
app:layout_constraintTop_toBottomOf=
"@+id/title_text_view"
app:layout_constraintVertical_bias=
"1.0"
tools:text=
"Advertiser"
tools:textSize=
"12sp"
/>
<FrameLayout
android:id=
"@+id/star_rating_view"
android:layout_width=
"wrap_content"
android:layout_height=
"0dp"
android:layout_marginTop=
"4dp"
app:layout_constraintBottom_toTopOf=
"@id/advertiser_text_view"
app:layout_constraintStart_toStartOf=
"@id/text_view"
app:layout_constraintTop_toBottomOf=
"@id/text_view"
/>
<TextView
android:id=
"@+id/body_text_view"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"8dp"
android:textAppearance=
"@style/TextAppearance.AppCompat.Body1"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/icon_image_view"
tools:text=
"Body"
/>
<FrameLayout
android:id=
"@+id/media_view_container"
android:layout_width=
"0dp"
android:layout_height=
"150dp"
android:layout_marginTop=
"4dp"
android:maxHeight=
"150dp"
app:layout_constraintDimensionRatio=
"W,16:9"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/body_text_view"
/>
<Button
android:id=
"@+id/cta_button"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"8dp"
android:backgroundTint=
"@color/applovin_sdk_brand_color"
android:textColor=
"@android:color/white"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/media_view_container"
tools:layout_editor_absoluteX=
"8dp"
tools:text=
"Install"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
app/src/main/res/mipmap-xxhdpi/icon_close.png
0 → 100644
View file @
e8ade6bb
1.03 KB
app/src/main/res/mipmap-xxhdpi/img_tongzhi_pop_bj.png
0 → 100644
View file @
e8ade6bb
283 KB
app/src/main/res/mipmap-xxhdpi/jiazai_ad.webp
0 → 100644
View file @
e8ade6bb
File added
app/src/main/res/values/strings.xml
View file @
e8ade6bb
...
@@ -64,4 +64,8 @@
...
@@ -64,4 +64,8 @@
<string
name=
"no_qrcode"
>
NO QRCode
</string>
<string
name=
"no_qrcode"
>
NO QRCode
</string>
<string
name=
"choose_language"
>
Choose language
</string>
<string
name=
"choose_language"
>
Choose language
</string>
<string
name=
"web_address"
>
Web address
</string>
<string
name=
"web_address"
>
Web address
</string>
<string
name=
"turn_on_notification"
>
Turn on notification
</string>
<string
name=
"turn_on"
>
Turn on
</string>
<string
name=
"preparing_advertisement"
>
Preparing advertisement
</string>
</resources>
</resources>
\ No newline at end of file
gradle/libs.versions.toml
View file @
e8ade6bb
...
@@ -13,6 +13,13 @@ immersionbar = "3.2.2"
...
@@ -13,6 +13,13 @@ immersionbar = "3.2.2"
navigationFragmentKtx
=
"2.6.0"
navigationFragmentKtx
=
"2.6.0"
navigationUiKtx
=
"2.6.0"
navigationUiKtx
=
"2.6.0"
playServicesAds
=
"23.5.0.0"
applovin
=
"13.0.1"
vungle
=
"7.4.2.0"
facebook
=
"6.18.0.0"
mintegral
=
"16.8.61.0"
pangle
=
"6.3.0.4.0"
[libraries]
[libraries]
androidx-core-ktx
=
{
group
=
"androidx.core"
,
name
=
"core-ktx"
,
version.ref
=
"coreKtx"
}
androidx-core-ktx
=
{
group
=
"androidx.core"
,
name
=
"core-ktx"
,
version.ref
=
"coreKtx"
}
...
@@ -29,6 +36,21 @@ androidx-navigation-fragment-ktx = { group = "androidx.navigation", name = "navi
...
@@ -29,6 +36,21 @@ androidx-navigation-fragment-ktx = { group = "androidx.navigation", name = "navi
androidx-navigation-ui-ktx
=
{
group
=
"androidx.navigation"
,
name
=
"navigation-ui-ktx"
,
version.ref
=
"navigationUiKtx"
}
androidx-navigation-ui-ktx
=
{
group
=
"androidx.navigation"
,
name
=
"navigation-ui-ktx"
,
version.ref
=
"navigationUiKtx"
}
vungle
=
{
group
=
"com.google.ads.mediation"
,
name
=
"vungle"
,
version.ref
=
"vungle"
}
facebook
=
{
group
=
"com.google.ads.mediation"
,
name
=
"facebook"
,
version.ref
=
"facebook"
}
mintegral
=
{
group
=
"com.google.ads.mediation"
,
name
=
"mintegral"
,
version.ref
=
"mintegral"
}
pangle
=
{
group
=
"com.google.ads.mediation"
,
name
=
"pangle"
,
version.ref
=
"pangle"
}
applovin
=
{
group
=
"com.applovin"
,
name
=
"applovin-sdk"
,
version.ref
=
"applovin"
}
applovin_google
=
{
group
=
"com.applovin.mediation"
,
name
=
"google-ad-manager-adapter"
,
version.ref
=
"playServicesAds"
}
applovin_admob
=
{
group
=
"com.applovin.mediation"
,
name
=
"google-adapter"
,
version.ref
=
"playServicesAds"
}
applovin_vungle
=
{
group
=
"com.applovin.mediation"
,
name
=
"vungle-adapter"
,
version.ref
=
"vungle"
}
applovin_facebook
=
{
group
=
"com.applovin.mediation"
,
name
=
"facebook-adapter"
,
version.ref
=
"facebook"
}
applovin_mintegral
=
{
group
=
"com.applovin.mediation"
,
name
=
"mintegral-adapter"
,
version.ref
=
"mintegral"
}
applovin_pangle
=
{
group
=
"com.applovin.mediation"
,
name
=
"bytedance-adapter"
,
version.ref
=
"pangle"
}
[plugins]
[plugins]
android-application
=
{
id
=
"com.android.application"
,
version.ref
=
"agp"
}
android-application
=
{
id
=
"com.android.application"
,
version.ref
=
"agp"
}
kotlin-android
=
{
id
=
"org.jetbrains.kotlin.android"
,
version.ref
=
"kotlin"
}
kotlin-android
=
{
id
=
"org.jetbrains.kotlin.android"
,
version.ref
=
"kotlin"
}
...
...
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