聚合tradplus平台。

This commit is contained in:
ocean 2025-12-16 17:50:42 +08:00
parent 544fe96be5
commit 1cfbfb32de
20 changed files with 342 additions and 624 deletions

View File

@ -36,8 +36,8 @@ android {
applicationId = "com.all.pdfreader.pdf.reader" applicationId = "com.all.pdfreader.pdf.reader"
minSdk = 24 minSdk = 24
targetSdk = 36 targetSdk = 36
versionCode = 6 versionCode = 7
versionName = "1.0.6" versionName = "1.0.7"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
setProperty("archivesBaseName", "${getAppNameFromStringsFile()}-$versionName($versionCode)-${timestamp}") setProperty("archivesBaseName", "${getAppNameFromStringsFile()}-$versionName($versionCode)-${timestamp}")
@ -119,10 +119,54 @@ dependencies {
implementation("com.google.firebase:firebase-crashlytics-ndk") implementation("com.google.firebase:firebase-crashlytics-ndk")
implementation("com.google.firebase:firebase-analytics") implementation("com.google.firebase:firebase-analytics")
// google ads // google ads
implementation("com.google.android.gms:play-services-ads:24.7.0") // implementation("com.google.android.gms:play-services-ads:24.7.0")
implementation ("com.google.android.gms:play-services-ads-identifier:18.0.1") // implementation ("com.google.android.gms:play-services-ads-identifier:18.0.1")
// okhttp // okhttp
implementation ("com.squareup.okhttp3:okhttp:4.12.0") implementation ("com.squareup.okhttp3:okhttp:4.12.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0") implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
// TradPlus
implementation("com.tradplusad:tradplus:15.1.10.1")
//noinspection GradleCompatible
implementation("androidx.legacy:legacy-support-v4:1.0.0")
implementation("androidx.appcompat:appcompat:1.3.0-alpha02")
// Ironsource
implementation("com.ironsource.sdk:mediationsdk:9.0.0")
implementation("com.tradplusad:tradplus-ironsource:10.15.1.10.1")
// Pangle
implementation("com.tradplusad:tradplus-pangle:19.15.1.10.1")
implementation("com.pangle.global:pag-sdk:7.7.0.2")
// UnityAds
implementation("com.tradplusad:tradplus-unity:5.15.1.10.1")
implementation("com.unity3d.ads:unity-ads:4.16.3")
// Inmobi
implementation("com.tradplusad:tradplus-inmobix:23.15.1.10.1")
implementation("com.inmobi.monetization:inmobi-ads-kotlin:11.0.0")
implementation("com.squareup.okhttp3:okhttp:3.14.9")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4")
implementation("androidx.core:core-ktx:1.5.0")
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.0")
implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
implementation("com.google.android.gms:play-services-location:21.0.1")
//optional dependency for better targeting
implementation("androidx.browser:browser:1.8.0")
implementation("com.squareup.picasso:picasso:2.8")
implementation("androidx.viewpager:viewpager:1.0.0")
implementation("androidx.recyclerview:recyclerview:1.2.1")
// Mintegral
implementation("com.tradplusad:tradplus-mintegralx_overseas:18.15.1.10.1")
implementation("androidx.recyclerview:recyclerview:1.1.0")
implementation("com.mbridge.msdk.oversea:mbridge_android_sdk:16.10.11")
// Liftoff
implementation("com.tradplusad:tradplus-vunglex:7.15.1.10.1")
implementation("com.vungle:vungle-ads:7.6.0")
// Bigo
implementation("com.bigossp:bigo-ads:5.5.2")
implementation("com.tradplusad:tradplus-bigo:57.15.1.10.1")
// Cross Promotion
implementation("com.tradplusad:tradplus-crosspromotion:27.15.1.10.1")
// TP Exchange
// 请注意保持与主包版本同步更新
implementation("com.google.code.gson:gson:2.8.6")
implementation("com.tradplusad:tp_exchange:40.15.1.10.1")
} }

View File

@ -51,3 +51,6 @@
-keepattributes *Annotation* -keepattributes *Annotation*
-keepattributes Signature -keepattributes Signature
-keepattributes InnerClasses -keepattributes InnerClasses
-keep public class com.tradplus.** { *; }
-keep class com.tradplus.ads.** { *; }

View File

@ -28,6 +28,8 @@
tools:ignore="ScopedStorage" /> tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.AD_ID" />
<application <application
android:name=".PRApp" android:name=".PRApp"
android:allowBackup="true" android:allowBackup="true"
@ -36,6 +38,7 @@
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:largeHeap="true" android:largeHeap="true"
tools:replace="networkSecurityConfig"
android:networkSecurityConfig="@xml/net" android:networkSecurityConfig="@xml/net"
android:requestLegacyExternalStorage="true" android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"

View File

@ -6,9 +6,8 @@ import androidx.annotation.StringRes
import com.all.pdfreader.pdf.reader.room.repository.PdfRepository import com.all.pdfreader.pdf.reader.room.repository.PdfRepository
import com.all.pdfreader.pdf.reader.util.AnalyticsUtils import com.all.pdfreader.pdf.reader.util.AnalyticsUtils
import com.all.pdfreader.pdf.reader.util.FileChangeObserver import com.all.pdfreader.pdf.reader.util.FileChangeObserver
import com.google.android.gms.ads.MobileAds
import com.google.android.gms.ads.RequestConfiguration
import com.tom_roush.pdfbox.android.PDFBoxResourceLoader import com.tom_roush.pdfbox.android.PDFBoxResourceLoader
import com.tradplus.ads.open.TradPlusSdk
import com.up.uploadlibrary.UpLoadManager import com.up.uploadlibrary.UpLoadManager
class PRApp : Application() { class PRApp : Application() {
@ -44,14 +43,12 @@ class PRApp : Application() {
PDFBoxResourceLoader.init(this) PDFBoxResourceLoader.init(this)
// 上传 // 上传
UpLoadManager.init(context = this, tag = "PRApp_upload_task") { _, _ -> } UpLoadManager.init(context = this, tag = "PRApp_upload_task") { _, _ -> }
// 广告初始化 initAds()
MobileAds.initialize(this)
} }
private fun initMobileAds() { private fun initAds() {
val testDeviceIds = listOf("9A96E667D69B45F744FD7D724DF8B093") // 广告初始化
val configuration = RequestConfiguration.Builder().setTestDeviceIds(testDeviceIds).build() TradPlusSdk.initSdk(this, "7D782C68D2CB653BE84B6912673BDF11")
MobileAds.setRequestConfiguration(configuration)
} }
// 在权限授权后调用 // 在权限授权后调用

View File

@ -3,10 +3,10 @@ package com.all.pdfreader.pdf.reader.ad
import android.app.Activity import android.app.Activity
import android.util.Log import android.util.Log
import com.all.pdfreader.pdf.reader.util.AnalyticsUtils import com.all.pdfreader.pdf.reader.util.AnalyticsUtils
import com.google.android.gms.ads.AdRequest import com.tradplus.ads.base.bean.TPAdError
import com.google.android.gms.ads.LoadAdError import com.tradplus.ads.base.bean.TPAdInfo
import com.google.android.gms.ads.interstitial.InterstitialAd import com.tradplus.ads.open.interstitial.InterstitialAdListener
import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback import com.tradplus.ads.open.interstitial.TPInterstitial
class AdInstLoad( class AdInstLoad(
private val activity: Activity, private val activity: Activity,
@ -19,11 +19,11 @@ class AdInstLoad(
} }
private fun loadAd() { private fun loadAd() {
Log.d(AdsInsUtil.Placement.TAG,"广告 $placement 开始加载") Log.d(AdsInsUtil.Placement.TAG, "广告 $placement 开始加载")
// 是否存在缓存广告、展示安全 // 是否存在缓存广告、展示安全
val cachedAd = InstAdCacheManager.instance.getAdCache(placement) val cachedAd = InstAdCacheManager.instance.getAdCache(placement)
if (cachedAd != null) { if (cachedAd != null) {
Log.d(AdsInsUtil.Placement.TAG,"广告存在缓存,跳过加载,返回成功") Log.d(AdsInsUtil.Placement.TAG, "广告存在缓存,跳过加载,返回成功")
//缓存广告有效,跳过加载,返回成功 //缓存广告有效,跳过加载,返回成功
adLoadListener?.loaded(cachedAd) adLoadListener?.loaded(cachedAd)
return return
@ -31,7 +31,7 @@ class AdInstLoad(
// 如果正在加载(其他地方已 load 加入等待队列 // 如果正在加载(其他地方已 load 加入等待队列
if (InstAdCacheManager.instance.isLoading(placement)) { if (InstAdCacheManager.instance.isLoading(placement)) {
Log.d(AdsInsUtil.Placement.TAG,"广告 $placement 正在加载中,加入等待队列") Log.d(AdsInsUtil.Placement.TAG, "广告 $placement 正在加载中,加入等待队列")
InstAdCacheManager.instance.addPendingListener(placement, adLoadListener) InstAdCacheManager.instance.addPendingListener(placement, adLoadListener)
return return
} }
@ -41,35 +41,68 @@ class AdInstLoad(
val adUnitId = AdsInsUtil.adUnitIdMap[placement] ?: run { val adUnitId = AdsInsUtil.adUnitIdMap[placement] ?: run {
val errorMsg = "No AdUnitId for $placement" val errorMsg = "No AdUnitId for $placement"
Log.d(AdsInsUtil.Placement.TAG,"没找到对应的广告ID->$placement") Log.d(AdsInsUtil.Placement.TAG, "没找到对应的广告ID->$placement")
InstAdCacheManager.instance.notifyFail(placement, errorMsg) InstAdCacheManager.instance.notifyFail(placement, errorMsg)
return return
} }
AnalyticsUtils.logAdEvent(placement, AnalyticsUtils.AdEvent.REQ) AnalyticsUtils.logAdEvent(placement, AnalyticsUtils.AdEvent.REQ)
Log.d(AdsInsUtil.Placement.TAG,"adUnitId->$adUnitId") Log.d(AdsInsUtil.Placement.TAG, "adUnitId->$adUnitId")
InterstitialAd.load(
activity, val tpInterstitial = TPInterstitial(activity, adUnitId)
adUnitId, tpInterstitial.setAdListener(object : InterstitialAdListener {
AdRequest.Builder().build(), //广告加载完成 首个广告源加载成功时回调 一次加载流程只会回调一次
object : InterstitialAdLoadCallback() { override fun onAdLoaded(tpAdInfo: TPAdInfo) {
override fun onAdLoaded(ad: InterstitialAd) { Log.d(AdsInsUtil.Placement.TAG, "广告 $placement 加载成功")
Log.d(AdsInsUtil.Placement.TAG,"广告 $placement 加载成功") InstAdCacheManager.instance.setAdCache(placement, tpInterstitial)
InstAdCacheManager.instance.setAdCache(placement, ad)
AnalyticsUtils.logAdEvent(placement, AnalyticsUtils.AdEvent.LOADED) AnalyticsUtils.logAdEvent(placement, AnalyticsUtils.AdEvent.LOADED)
InstAdCacheManager.instance.notifySuccess(placement, ad) InstAdCacheManager.instance.notifySuccess(placement, tpInterstitial)
} }
override fun onAdFailedToLoad(adError: LoadAdError) { // 广告被点击
Log.d(AdsInsUtil.Placement.TAG,"广告 $placement 加载失败") override fun onAdClicked(tpAdInfo: TPAdInfo?) {
Log.d("ocean", "tradplus onAdClicked")
}
// 广告成功展示在页面上
override fun onAdImpression(tpAdInfo: TPAdInfo?) {
Log.d("ocean", "tradplus onAdImpression")
}
// 广告加载失败
override fun onAdFailed(error: TPAdError?) {
Log.d(AdsInsUtil.Placement.TAG, "广告 $placement 加载失败 ${error?.errorCode} ${error?.errorMsg}")
AnalyticsUtils.logAdEvent( AnalyticsUtils.logAdEvent(
placement, placement,
AnalyticsUtils.AdEvent.LOAD_FAIL, AnalyticsUtils.AdEvent.LOAD_FAIL,
adError.code, error?.errorCode,
adError.message error?.errorMsg
) )
InstAdCacheManager.instance.notifyFail(placement, adError.toString()) InstAdCacheManager.instance.notifyFail(placement, "${error?.errorCode} ${error?.errorMsg}")
} }
},
// 广告被关闭
override fun onAdClosed(tpAdInfo: TPAdInfo?) {
Log.d("ocean", "tradplus onAdClosed")
}
// 视频播放开始(部分广告源支持)
override fun onAdVideoStart(tpAdInfo: TPAdInfo?) {
Log.d("ocean", "tradplus onAdVideoStart")
}
//视频播放结束(部分广告源支持)
override fun onAdVideoEnd(tpAdInfo: TPAdInfo?) {
Log.d("ocean", "tradplus onAdVideoEnd")
}
//视频播放失败(部分广告源支持)
override fun onAdVideoError(tpAdInfo: TPAdInfo?, error: TPAdError?) {
Log.d(
"ocean",
"onAdVideoError code->${error?.errorCode}message->${error?.errorMsg}"
) )
} }
})
tpInterstitial.loadAd()
}
} }

View File

@ -3,8 +3,9 @@ package com.all.pdfreader.pdf.reader.ad
import android.app.Activity import android.app.Activity
import android.util.Log import android.util.Log
import com.all.pdfreader.pdf.reader.util.AnalyticsUtils import com.all.pdfreader.pdf.reader.util.AnalyticsUtils
import com.google.android.gms.ads.AdError import com.tradplus.ads.base.bean.TPAdError
import com.google.android.gms.ads.FullScreenContentCallback import com.tradplus.ads.base.bean.TPAdInfo
import com.tradplus.ads.open.interstitial.InterstitialAdListener
class AdInstShower( class AdInstShower(
private val activity: Activity, private val activity: Activity,
@ -23,22 +24,22 @@ class AdInstShower(
private fun showAd() { private fun showAd() {
// ======= 新增:全局展示间隔限制 启动页不处理 ======= // ======= 新增:全局展示间隔限制 启动页不处理 =======
if(placement != AdsInsUtil.AdPlacement.SPL_AND_INTO_HOME){ // if(placement != AdsInsUtil.AdPlacement.SPL_AND_INTO_HOME){
val now = System.currentTimeMillis() // val now = System.currentTimeMillis()
if (now - lastShowTimestamp < SHOW_INTERVAL) { // if (now - lastShowTimestamp < SHOW_INTERVAL) {
val errorMsg = "广告展示过于频繁, 请等待 ${(SHOW_INTERVAL - (now - lastShowTimestamp)) / 1000}s间隔限制60s" // val errorMsg = "广告展示过于频繁, 请等待 ${(SHOW_INTERVAL - (now - lastShowTimestamp)) / 1000}s间隔限制60s"
showListener?.onAdShowFailed(errorMsg) // showListener?.onAdShowFailed(errorMsg)
Log.d(AdsInsUtil.Placement.TAG, "showAd->$errorMsg") // Log.d(AdsInsUtil.Placement.TAG, "showAd->$errorMsg")
//
AnalyticsUtils.logAdEvent( // AnalyticsUtils.logAdEvent(
placement, // placement,
AnalyticsUtils.AdEvent.SHOW_FAIL_ME, // AnalyticsUtils.AdEvent.SHOW_FAIL_ME,
1001, // 1001,
errorMsg // errorMsg
) // )
return // return
} // }
} // }
val interstitialAd = InstAdCacheManager.instance.getAdCache(placement) val interstitialAd = InstAdCacheManager.instance.getAdCache(placement)
?: run { ?: run {
@ -55,43 +56,55 @@ class AdInstShower(
return return
} }
interstitialAd.fullScreenContentCallback = object : FullScreenContentCallback() { interstitialAd.setAdListener(object : InterstitialAdListener {
//广告加载完成 首个广告源加载成功时回调 一次加载流程只会回调一次
override fun onAdLoaded(tpAdInfo: TPAdInfo?) {}
override fun onAdShowedFullScreenContent() { // 广告被点击
// ======= 新增:展示成功 记录时间 ======= override fun onAdClicked(tpAdInfo: TPAdInfo?) {
showListener?.onAdClicked()
Log.d("ocean", "AdInstShower 广告点击回调")
}
// 广告成功展示在页面上
override fun onAdImpression(tpAdInfo: TPAdInfo?) {
lastShowTimestamp = System.currentTimeMillis() lastShowTimestamp = System.currentTimeMillis()
Log.d(AdsInsUtil.Placement.TAG, "广告 $placement 展示成功") Log.d(AdsInsUtil.Placement.TAG, "广告 $placement 展示成功")
AnalyticsUtils.logAdEvent(placement, AnalyticsUtils.AdEvent.SHOW_SUC) AnalyticsUtils.logAdEvent(placement, AnalyticsUtils.AdEvent.SHOW_SUC)
showListener?.onAdShown() showListener?.onAdShown()
} }
override fun onAdDismissedFullScreenContent() { // 广告加载失败
override fun onAdFailed(error: TPAdError?) {}
// 广告被关闭
override fun onAdClosed(tpAdInfo: TPAdInfo?) {
// 用户关闭广告 // 用户关闭广告
InstAdCacheManager.instance.remove(placement) InstAdCacheManager.instance.remove(placement)
showListener?.onAdClosed() showListener?.onAdClosed()
Log.d("ocean", "AdInstShower 广告关闭回调")
} }
override fun onAdFailedToShowFullScreenContent(adError: AdError) { // 视频播放开始(部分广告源支持)
override fun onAdVideoStart(tpAdInfo: TPAdInfo?) {}
//视频播放结束(部分广告源支持)
override fun onAdVideoEnd(tpAdInfo: TPAdInfo?) {}
//视频播放失败(部分广告源支持)
override fun onAdVideoError(tpAdInfo: TPAdInfo?, error: TPAdError?) {
Log.d("ocean", "AdInstShower 视频广告播放失败回调->${error}")
AnalyticsUtils.logAdEvent( AnalyticsUtils.logAdEvent(
placement, placement,
AnalyticsUtils.AdEvent.SHOW_FAIL, AnalyticsUtils.AdEvent.SHOW_FAIL,
adError.code, error?.errorCode,
adError.message error?.errorMsg
) )
InstAdCacheManager.instance.remove(placement) InstAdCacheManager.instance.remove(placement)
showListener?.onAdShowFailed(adError.toString()) showListener?.onAdShowFailed(error.toString())
Log.d(AdsInsUtil.Placement.TAG, "广告 $placement 展示失败->${adError}") Log.d(AdsInsUtil.Placement.TAG, "广告 $placement 展示失败->${error}")
} }
})
override fun onAdClicked() { interstitialAd.showAd(activity, placement.tag)
showListener?.onAdClicked()
}
override fun onAdImpression() {
// 曝光回调
}
}
interstitialAd.show(activity)
} }
} }

View File

@ -8,11 +8,7 @@ object AdsInsUtil {
enum class AdPlacement(val tag: String) { enum class AdPlacement(val tag: String) {
SPL_AND_INTO_HOME(Placement.SPL_AND_INTO_HOME), SPL_AND_INTO_HOME(Placement.SPL_AND_INTO_HOME),
INT_AND_TOPDF(Placement.INT_AND_TOPDF), INT_AND_TOPDF(Placement.INT_AND_TOPDF),
INT_AND_PDFTOHOME(Placement.INT_AND_PDFTOHOME), INT_AND_TO_RESULT(Placement.INT_AND_TO_RESULT),
INT_AND_MERGE(Placement.INT_AND_MERGE),
INT_AND_SPLIT(Placement.INT_AND_SPLIT),
NATIVE_AND_EXIT(Placement.NATIVE_AND_EXIT),
BAN_AND_HOMEPAGE(Placement.BAN_AND_HOMEPAGE)
} }
object Placement { object Placement {
@ -27,11 +23,7 @@ object AdsInsUtil {
* 在首页/最近页/喜欢页-点击文件进入PDF内容页过程中弹出缓存的插屏广告 * 在首页/最近页/喜欢页-点击文件进入PDF内容页过程中弹出缓存的插屏广告
*/ */
const val INT_AND_TOPDF = "int_and_topdf" const val INT_AND_TOPDF = "int_and_topdf"
const val INT_AND_TO_RESULT = "int_and_to_result"
/**
* PDF内容页点击返回到首页/最近页/喜欢页过程中弹出缓存的插屏广告
*/
const val INT_AND_PDFTOHOME = "int_and_pdftohome"
/** /**
* 首页/最近/喜欢-PDF内容页-更多-合并文件在点击ok后出现插屏广告插屏广告结束后到合并成功页面 * 首页/最近/喜欢-PDF内容页-更多-合并文件在点击ok后出现插屏广告插屏广告结束后到合并成功页面
@ -56,41 +48,9 @@ object AdsInsUtil {
// 广告位对应的广告ID // 广告位对应的广告ID
val adUnitIdMap: Map<AdPlacement, String> = mapOf( val adUnitIdMap: Map<AdPlacement, String> = mapOf(
AdPlacement.SPL_AND_INTO_HOME to if (BuildConfig.DEBUG) { AdPlacement.SPL_AND_INTO_HOME to "B421758030611F925EE37C791CCDDA12",
"ca-app-pub-3940256099942544/1033173712" AdPlacement.INT_AND_TOPDF to "558381BCAC5CF8CEEFFD26B668C4AD12",
} else { AdPlacement.INT_AND_TO_RESULT to "746C9253315481118A10AF5417F1FB12",
"ca-app-pub-5717753826607607/9606833210"
},
AdPlacement.INT_AND_TOPDF to if (BuildConfig.DEBUG) {
"ca-app-pub-3940256099942544/1033173712"
} else {
"ca-app-pub-5717753826607607/5308904672"
},
AdPlacement.INT_AND_PDFTOHOME to if (BuildConfig.DEBUG) {
"ca-app-pub-3940256099942544/1033173712"
} else {
"ca-app-pub-5717753826607607/7085128570"
},
AdPlacement.INT_AND_MERGE to if (BuildConfig.DEBUG) {
"ca-app-pub-3940256099942544/1033173712"
} else {
"ca-app-pub-5717753826607607/8928693282"
},
AdPlacement.INT_AND_SPLIT to if (BuildConfig.DEBUG) {
"ca-app-pub-3940256099942544/1033173712"
} else {
"ca-app-pub-5717753826607607/2338415962"
},
AdPlacement.NATIVE_AND_EXIT to if (BuildConfig.DEBUG) {
"ca-app-pub-3940256099942544/2247696110"
} else {
"ca-app-pub-5717753826607607/7276700267"
},
AdPlacement.BAN_AND_HOMEPAGE to if (BuildConfig.DEBUG) {
"ca-app-pub-3940256099942544/9214589741"
} else {
"ca-app-pub-5717753826607607/5939567861"
}
) )
fun loadAd( fun loadAd(

View File

@ -1,132 +0,0 @@
package com.all.pdfreader.pdf.reader.ad
import android.app.Activity
import android.util.DisplayMetrics
import android.util.Log
import android.view.View
import android.widget.FrameLayout
import com.all.pdfreader.pdf.reader.util.AnalyticsUtils
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
object BannerManager {
private data class BannerInfo(val adView: AdView, val container: FrameLayout, var isLoaded: Boolean = false)
private val bannerMap = mutableMapOf<String, BannerInfo>()
//因为有多个activity来展示这个banner所以我们使用act的名称+广告位做为key
private fun key(placement: AdsInsUtil.AdPlacement, activity: Activity): String {
return "${placement.name}_${activity::class.java.simpleName}"
}
fun loadBanner(
activity: Activity,
container: FrameLayout,
placement: AdsInsUtil.AdPlacement,
onLoaded: (() -> Unit)? = null
) {
val currentKey = key(placement, activity)//得到当前的key
val adUnitId = AdsInsUtil.adUnitIdMap[placement] ?: run {
Log.d(AdsInsUtil.Placement.TAG, "${activity::class.java.simpleName} Banner 未找到广告ID: $placement")
container.visibility = View.GONE
return
}
Log.d(AdsInsUtil.Placement.TAG, "${activity::class.java.simpleName} Banner $placement 开始加载")
AnalyticsUtils.logAdEvent(placement, AnalyticsUtils.AdEvent.REQ)
container.post {
container.visibility = View.GONE
val adSize = getAdSize(activity, container)
// 销毁旧 AdView
bannerMap[currentKey]?.adView?.destroy()
val adView = AdView(activity).apply {
this.adUnitId = adUnitId
setAdSize(adSize)
adListener = object : AdListener() {
override fun onAdLoaded() {
Log.d(AdsInsUtil.Placement.TAG, "${activity::class.java.simpleName} Banner $placement 加载成功")
AnalyticsUtils.logAdEvent(placement, AnalyticsUtils.AdEvent.LOADED)
val info = bannerMap[currentKey]
info?.isLoaded = true
// 广告加载成功后显示容器
info?.container?.visibility = View.VISIBLE
info?.container?.alpha = 0f
info?.container?.animate()?.alpha(1f)?.setDuration(300)?.start()
onLoaded?.invoke()
}
override fun onAdFailedToLoad(error: LoadAdError) {
Log.d(AdsInsUtil.Placement.TAG, "${activity::class.java.simpleName} Banner $placement 加载失败: ${error.message}")
AnalyticsUtils.logAdEvent(
placement,
AnalyticsUtils.AdEvent.LOAD_FAIL,
error.code,
error.message
)
val info = bannerMap[currentKey]
info?.isLoaded = false
info?.container?.visibility = View.GONE
}
}
}
bannerMap[currentKey] = BannerInfo(adView, container)
container.removeAllViews()
container.addView(adView)
adView.loadAd(AdRequest.Builder().build())
}
}
fun onResume(activity: Activity, placement: AdsInsUtil.AdPlacement) {
Log.d(AdsInsUtil.Placement.TAG, "${activity::class.java.simpleName} Banner $placement 恢复广告")
val info = bannerMap[key(placement, activity)] ?: return
info.adView.resume()
if (info.isLoaded) {
info.container.visibility = View.VISIBLE
info.container.alpha = 0f
info.container.animate().alpha(1f).setDuration(300).start()
} else {
info.container.visibility = View.GONE
}
}
fun onPause(activity: Activity, placement: AdsInsUtil.AdPlacement) {
val info = bannerMap[key(placement, activity)] ?: return
info.container.visibility = View.GONE//暂停后就隐藏,让回调来显示
info.adView.pause()
Log.d(AdsInsUtil.Placement.TAG, "${activity::class.java.simpleName} Banner $placement 暂停广告")
}
fun onDestroy(activity: Activity, placement: AdsInsUtil.AdPlacement) {
val key = key(placement, activity)
bannerMap[key]?.adView?.destroy()
bannerMap.remove(key)
Log.d(AdsInsUtil.Placement.TAG, "${activity::class.java.simpleName} Banner $placement 销毁广告")
}
private fun getAdSize(activity: Activity, container: FrameLayout): AdSize {
val display = activity.windowManager.defaultDisplay
val outMetrics = DisplayMetrics()
display.getMetrics(outMetrics)
var adWidthPixels = container.width.toFloat()
if (adWidthPixels == 0f) adWidthPixels = outMetrics.widthPixels.toFloat()
val density = outMetrics.density
val adWidth = (adWidthPixels / density).toInt()
return AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(activity, adWidth)
}
}

View File

@ -1,6 +1,6 @@
package com.all.pdfreader.pdf.reader.ad package com.all.pdfreader.pdf.reader.ad
import com.google.android.gms.ads.interstitial.InterstitialAd import com.tradplus.ads.open.interstitial.TPInterstitial
class InstAdCacheManager { class InstAdCacheManager {
@ -39,7 +39,7 @@ class InstAdCacheManager {
} }
fun notifySuccess(place: AdsInsUtil.AdPlacement, ad: InterstitialAd) { fun notifySuccess(place: AdsInsUtil.AdPlacement, ad: TPInterstitial) {
pendingListeners[place]?.forEach { it?.loaded(ad) } pendingListeners[place]?.forEach { it?.loaded(ad) }
pendingListeners.remove(place) pendingListeners.remove(place)
loadingSet.remove(place) loadingSet.remove(place)
@ -53,13 +53,13 @@ class InstAdCacheManager {
/** ============= 广告缓存逻辑 ============= */ /** ============= 广告缓存逻辑 ============= */
fun setAdCache(place: AdsInsUtil.AdPlacement, adCache: InterstitialAd) { fun setAdCache(place: AdsInsUtil.AdPlacement, adCache: TPInterstitial) {
mAdCacheDict[place] = CachedAd(adCache) mAdCacheDict[place] = CachedAd(adCache)
} }
fun getAdCache(place: AdsInsUtil.AdPlacement): InterstitialAd? { fun getAdCache(place: AdsInsUtil.AdPlacement): TPInterstitial? {
val cached = mAdCacheDict[place] val cached = mAdCacheDict[place]
return if (cached != null && cached.isValid()) cached.ad return if (cached != null && cached.ad.isReady) cached.ad
else { else {
mAdCacheDict.remove(place) // 清理过期 mAdCacheDict.remove(place) // 清理过期
null null
@ -74,10 +74,7 @@ class InstAdCacheManager {
* 包装广告 + 时间 * 包装广告 + 时间
*/ */
data class CachedAd( data class CachedAd(
val ad: InterstitialAd, val ad: TPInterstitial,
val loadedAt: Long = System.currentTimeMillis()
) { ) {
// 广告有效期 1 小时
fun isValid(): Boolean = System.currentTimeMillis() - loadedAt < 3600_000
} }
} }

View File

@ -1,8 +1,8 @@
package com.all.pdfreader.pdf.reader.ad package com.all.pdfreader.pdf.reader.ad
import com.google.android.gms.ads.interstitial.InterstitialAd import com.tradplus.ads.open.interstitial.TPInterstitial
interface LoadListener { interface LoadListener {
fun loadFailed(string: String) {} fun loadFailed(string: String) {}
fun loaded(ad: InterstitialAd) {} fun loaded(ad: TPInterstitial) {}
} }

View File

@ -1,74 +0,0 @@
package com.all.pdfreader.pdf.reader.ad
import android.app.Activity
import android.content.Context
import android.util.Log
import com.all.pdfreader.pdf.reader.util.AnalyticsUtils
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
object NativeAdCache {
private var cachedAd: NativeAd? = null
fun load(
context: Context,
placement: AdsInsUtil.AdPlacement,
onAdLoaded: (() -> Unit)? = null,
onAdFailedToLoad: (() -> Unit)? = null
) {
if (cachedAd != null) {
onAdLoaded?.invoke()
return
}
val adUnitId = AdsInsUtil.adUnitIdMap[placement] ?: run {
val errorMsg = "No AdUnitId for $placement"
Log.d(AdsInsUtil.Placement.TAG, "没找到对应的广告ID->$placement")
onAdFailedToLoad?.invoke()
return
}
AnalyticsUtils.logAdEvent(placement, AnalyticsUtils.AdEvent.REQ)
val adLoader = AdLoader.Builder(context, adUnitId)
.forNativeAd { ad ->
if (context is Activity) {
if (context.isFinishing || context.isDestroyed) {
ad.destroy()
return@forNativeAd
}
}
cachedAd?.destroy()
cachedAd = ad
onAdLoaded?.invoke()
}
.withAdListener(object : AdListener() {
override fun onAdFailedToLoad(error: LoadAdError) {
cachedAd = null
onAdFailedToLoad?.invoke()
Log.d(AdsInsUtil.Placement.TAG, "$placement 广告加载失败 ${error.message}")
AnalyticsUtils.logAdEvent(
placement,
AnalyticsUtils.AdEvent.LOAD_FAIL,
error.code,
error.message
)
}
override fun onAdLoaded() {
Log.d(AdsInsUtil.Placement.TAG, "$placement 广告加载成功")
AnalyticsUtils.logAdEvent(placement, AnalyticsUtils.AdEvent.LOADED)
}
})
.build()
adLoader.loadAd(AdRequest.Builder().build())
}
fun getAd(): NativeAd? = cachedAd
fun clear() {
cachedAd?.destroy()
cachedAd = null
}
}

View File

@ -15,8 +15,6 @@ import androidx.lifecycle.lifecycleScope
import com.all.pdfreader.pdf.reader.PRApp import com.all.pdfreader.pdf.reader.PRApp
import com.all.pdfreader.pdf.reader.R import com.all.pdfreader.pdf.reader.R
import com.all.pdfreader.pdf.reader.ad.AdsInsUtil import com.all.pdfreader.pdf.reader.ad.AdsInsUtil
import com.all.pdfreader.pdf.reader.ad.BannerManager
import com.all.pdfreader.pdf.reader.ad.NativeAdCache
import com.all.pdfreader.pdf.reader.databinding.ActivityMainBinding import com.all.pdfreader.pdf.reader.databinding.ActivityMainBinding
import com.all.pdfreader.pdf.reader.model.FileActionEvent import com.all.pdfreader.pdf.reader.model.FileActionEvent
import com.all.pdfreader.pdf.reader.model.FragmentType import com.all.pdfreader.pdf.reader.model.FragmentType
@ -39,16 +37,6 @@ import com.all.pdfreader.pdf.reader.util.PdfScanner
import com.all.pdfreader.pdf.reader.util.StoragePermissionHelper import com.all.pdfreader.pdf.reader.util.StoragePermissionHelper
import com.all.pdfreader.pdf.reader.viewmodel.PdfViewModel import com.all.pdfreader.pdf.reader.viewmodel.PdfViewModel
import com.all.pdfreader.pdf.reader.viewmodel.observeEvent import com.all.pdfreader.pdf.reader.viewmodel.observeEvent
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.AdSize
import com.google.android.gms.ads.AdView
import com.google.android.gms.ads.LoadAdError
import com.google.android.gms.ads.nativead.NativeAdOptions
import com.google.android.gms.ads.nativead.NativeAdView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.File import java.io.File
@ -76,7 +64,6 @@ class MainActivity : BaseActivity(), PermissionDialogFragment.PermissionCallback
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater) binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
loadAd()
AnalyticsUtils.logEvent(AnalyticsUtils.Event.HOME_SHOW) AnalyticsUtils.logEvent(AnalyticsUtils.Event.HOME_SHOW)
setupDoubleBackExit() setupDoubleBackExit()
initObserve() initObserve()
@ -579,16 +566,17 @@ class MainActivity : BaseActivity(), PermissionDialogFragment.PermissionCallback
private fun loadAd() { private fun loadAd() {
AdsInsUtil.loadAd(this, AdsInsUtil.AdPlacement.INT_AND_TOPDF) AdsInsUtil.loadAd(this, AdsInsUtil.AdPlacement.INT_AND_TOPDF)
AdsInsUtil.loadAd(this, AdsInsUtil.AdPlacement.INT_AND_PDFTOHOME) AdsInsUtil.loadAd(this, AdsInsUtil.AdPlacement.INT_AND_TO_RESULT)
NativeAdCache.load(this, AdsInsUtil.AdPlacement.NATIVE_AND_EXIT) // NativeAdCache.load(this, AdsInsUtil.AdPlacement.NATIVE_AND_EXIT)
//
BannerManager.loadBanner(this, binding.bannerAdFl, AdsInsUtil.AdPlacement.BAN_AND_HOMEPAGE) // BannerManager.loadBanner(this, binding.bannerAdFl, AdsInsUtil.AdPlacement.BAN_AND_HOMEPAGE)
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
BannerManager.onResume(this, AdsInsUtil.AdPlacement.BAN_AND_HOMEPAGE) loadAd()
// BannerManager.onResume(this, AdsInsUtil.AdPlacement.BAN_AND_HOMEPAGE)
logDebug("main onResume") logDebug("main onResume")
if (StoragePermissionHelper.hasBasicStoragePermission(this)) { if (StoragePermissionHelper.hasBasicStoragePermission(this)) {
// 有授权才初始化文件变化监听器 // 有授权才初始化文件变化监听器
@ -605,12 +593,12 @@ class MainActivity : BaseActivity(), PermissionDialogFragment.PermissionCallback
} }
override fun onPause() { override fun onPause() {
BannerManager.onPause(this, AdsInsUtil.AdPlacement.BAN_AND_HOMEPAGE) // BannerManager.onPause(this, AdsInsUtil.AdPlacement.BAN_AND_HOMEPAGE)
super.onPause() super.onPause()
} }
override fun onDestroy() { override fun onDestroy() {
BannerManager.onDestroy(this, AdsInsUtil.AdPlacement.BAN_AND_HOMEPAGE) // BannerManager.onDestroy(this, AdsInsUtil.AdPlacement.BAN_AND_HOMEPAGE)
super.onDestroy() super.onDestroy()
} }

View File

@ -43,7 +43,7 @@ class MergePdfActivity : BaseActivity() {
binding = ActivityPdfMergeBinding.inflate(layoutInflater) binding = ActivityPdfMergeBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
AnalyticsUtils.logEvent(AnalyticsUtils.Event.MERGE_SHOW) AnalyticsUtils.logEvent(AnalyticsUtils.Event.MERGE_SHOW)
AdsInsUtil.loadAd(this, AdsInsUtil.AdPlacement.INT_AND_MERGE) // AdsInsUtil.loadAd(this, AdsInsUtil.AdPlacement.INT_AND_MERGE)
setupImmersionBar { setupImmersionBar {
statusBarView(binding.view) statusBarView(binding.view)
statusBarDarkFont(true) statusBarDarkFont(true)

View File

@ -130,6 +130,15 @@ class PdfResultActivity : BaseActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityPdfSplitResultBinding.inflate(layoutInflater) binding = ActivityPdfSplitResultBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
AdsInsUtil.showFinishAd(
this,
AdsInsUtil.AdPlacement.INT_AND_TO_RESULT
) {
AdsInsUtil.loadAd(
this,
AdsInsUtil.AdPlacement.INT_AND_TO_RESULT
)
}
setupImmersionBar { setupImmersionBar {
statusBarView(binding.view) statusBarView(binding.view)
statusBarDarkFont(true) statusBarDarkFont(true)
@ -162,9 +171,9 @@ class PdfResultActivity : BaseActivity() {
if (source == PdfPickerSource.SPLIT) { if (source == PdfPickerSource.SPLIT) {
val splitPassword = intent.getStringExtra(EXTRA_SPLIT_PASSWORD) ?: "" val splitPassword = intent.getStringExtra(EXTRA_SPLIT_PASSWORD) ?: ""
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
AdsInsUtil.showFinishAd(this@PdfResultActivity, AdsInsUtil.AdPlacement.INT_AND_SPLIT){ // AdsInsUtil.showFinishAd(this@PdfResultActivity, AdsInsUtil.AdPlacement.INT_AND_SPLIT){
AdsInsUtil.loadAd(this@PdfResultActivity, AdsInsUtil.AdPlacement.INT_AND_SPLIT) // AdsInsUtil.loadAd(this@PdfResultActivity, AdsInsUtil.AdPlacement.INT_AND_SPLIT)
} // }
binding.progressBar.isIndeterminate = false binding.progressBar.isIndeterminate = false
binding.progressBar.progress = 0 binding.progressBar.progress = 0
@ -216,9 +225,9 @@ class PdfResultActivity : BaseActivity() {
} }
} else if (source == PdfPickerSource.MERGE) { } else if (source == PdfPickerSource.MERGE) {
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
AdsInsUtil.showFinishAd(this@PdfResultActivity, AdsInsUtil.AdPlacement.INT_AND_MERGE){ // AdsInsUtil.showFinishAd(this@PdfResultActivity, AdsInsUtil.AdPlacement.INT_AND_MERGE){
AdsInsUtil.loadAd(this@PdfResultActivity, AdsInsUtil.AdPlacement.INT_AND_MERGE) // AdsInsUtil.loadAd(this@PdfResultActivity, AdsInsUtil.AdPlacement.INT_AND_MERGE)
} // }
binding.progressBar.isIndeterminate = false binding.progressBar.isIndeterminate = false
binding.progressBar.progress = 0 binding.progressBar.progress = 0
binding.progressBar.max = 100 binding.progressBar.max = 100

View File

@ -14,7 +14,6 @@ import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.all.pdfreader.pdf.reader.R import com.all.pdfreader.pdf.reader.R
import com.all.pdfreader.pdf.reader.ad.AdsInsUtil import com.all.pdfreader.pdf.reader.ad.AdsInsUtil
import com.all.pdfreader.pdf.reader.ad.BannerManager
import com.all.pdfreader.pdf.reader.databinding.ActivityPdfViewBinding import com.all.pdfreader.pdf.reader.databinding.ActivityPdfViewBinding
import com.all.pdfreader.pdf.reader.model.FileActionEvent import com.all.pdfreader.pdf.reader.model.FileActionEvent
import com.all.pdfreader.pdf.reader.room.entity.PdfDocumentEntity import com.all.pdfreader.pdf.reader.room.entity.PdfDocumentEntity
@ -82,7 +81,7 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
binding = ActivityPdfViewBinding.inflate(layoutInflater) binding = ActivityPdfViewBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
AnalyticsUtils.logEvent(AnalyticsUtils.Event.PDF_SHOW) AnalyticsUtils.logEvent(AnalyticsUtils.Event.PDF_SHOW)
BannerManager.loadBanner(this, binding.bannerAdFl, AdsInsUtil.AdPlacement.BAN_AND_HOMEPAGE) // BannerManager.loadBanner(this, binding.bannerAdFl, AdsInsUtil.AdPlacement.BAN_AND_HOMEPAGE)
setupImmersionBar { setupImmersionBar {
statusBarView(binding.view) statusBarView(binding.view)
statusBarDarkFont(true) statusBarDarkFont(true)
@ -490,15 +489,6 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
} }
} else { } else {
AnalyticsUtils.logEvent(AnalyticsUtils.Event.PDFTO_HOME_CK) AnalyticsUtils.logEvent(AnalyticsUtils.Event.PDFTO_HOME_CK)
AdsInsUtil.showFinishAd(
this@PdfViewActivity,
AdsInsUtil.AdPlacement.INT_AND_PDFTOHOME
) {
AdsInsUtil.loadAd(
this@PdfViewActivity,
AdsInsUtil.AdPlacement.INT_AND_PDFTOHOME
)
}
isEnabled = false // 解除拦截 isEnabled = false // 解除拦截
onBackPressedDispatcher.onBackPressed() // 调用系统默认返回逻辑 onBackPressedDispatcher.onBackPressed() // 调用系统默认返回逻辑
} }
@ -606,7 +596,7 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
} }
override fun onDestroy() { override fun onDestroy() {
BannerManager.onDestroy(this, AdsInsUtil.AdPlacement.BAN_AND_HOMEPAGE) // BannerManager.onDestroy(this, AdsInsUtil.AdPlacement.BAN_AND_HOMEPAGE)
super.onDestroy() super.onDestroy()
if (::searchManager.isInitialized) { if (::searchManager.isInitialized) {
searchManager.closeCachedDocument() searchManager.closeCachedDocument()
@ -615,11 +605,11 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
BannerManager.onResume(this, AdsInsUtil.AdPlacement.BAN_AND_HOMEPAGE) // BannerManager.onResume(this, AdsInsUtil.AdPlacement.BAN_AND_HOMEPAGE)
} }
override fun onPause() { override fun onPause() {
BannerManager.onPause(this, AdsInsUtil.AdPlacement.BAN_AND_HOMEPAGE) // BannerManager.onPause(this, AdsInsUtil.AdPlacement.BAN_AND_HOMEPAGE)
super.onPause() super.onPause()
} }
} }

View File

@ -5,18 +5,13 @@ import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.util.Log
import androidx.activity.OnBackPressedCallback
import androidx.core.view.doOnPreDraw
import com.all.pdfreader.pdf.reader.R
import com.all.pdfreader.pdf.reader.ad.AdsInsUtil import com.all.pdfreader.pdf.reader.ad.AdsInsUtil
import com.all.pdfreader.pdf.reader.ad.LoadListener import com.all.pdfreader.pdf.reader.ad.LoadListener
import com.all.pdfreader.pdf.reader.ad.ShowListener import com.all.pdfreader.pdf.reader.ad.ShowListener
import com.all.pdfreader.pdf.reader.databinding.ActivitySplashBinding import com.all.pdfreader.pdf.reader.databinding.ActivitySplashBinding
import com.all.pdfreader.pdf.reader.util.AnalyticsUtils import com.all.pdfreader.pdf.reader.util.AnalyticsUtils
import com.google.android.gms.ads.interstitial.InterstitialAd
import com.gyf.immersionbar.BarHide import com.gyf.immersionbar.BarHide
import com.gyf.immersionbar.ImmersionBar import com.tradplus.ads.open.interstitial.TPInterstitial
@SuppressLint("CustomSplashScreen") @SuppressLint("CustomSplashScreen")
class SplashActivity : BaseActivity() { class SplashActivity : BaseActivity() {
@ -56,7 +51,7 @@ class SplashActivity : BaseActivity() {
act = this, act = this,
adPlacement = AdsInsUtil.AdPlacement.SPL_AND_INTO_HOME, adPlacement = AdsInsUtil.AdPlacement.SPL_AND_INTO_HOME,
loadListener = object : LoadListener { loadListener = object : LoadListener {
override fun loaded(ad: InterstitialAd) { override fun loaded(ad: TPInterstitial) {
logDebug("loaded 启动页广告加载成功") logDebug("loaded 启动页广告加载成功")
adHandler.removeCallbacks(adTimeoutRunnable) adHandler.removeCallbacks(adTimeoutRunnable)
showSplashAd() showSplashAd()

View File

@ -65,7 +65,7 @@ class SplitPdfActivity : BaseActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityPdfSplitBinding.inflate(layoutInflater) binding = ActivityPdfSplitBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
AdsInsUtil.loadAd(this, AdsInsUtil.AdPlacement.INT_AND_SPLIT) // AdsInsUtil.loadAd(this, AdsInsUtil.AdPlacement.INT_AND_SPLIT)
setupImmersionBar { setupImmersionBar {
statusBarView(binding.view) statusBarView(binding.view)
statusBarDarkFont(true) statusBarDarkFont(true)

View File

@ -1,17 +1,12 @@
package com.all.pdfreader.pdf.reader.ui.dialog package com.all.pdfreader.pdf.reader.ui.dialog
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import com.all.pdfreader.pdf.reader.R import com.all.pdfreader.pdf.reader.R
import com.all.pdfreader.pdf.reader.ad.AdsInsUtil
import com.all.pdfreader.pdf.reader.ad.NativeAdCache
import com.all.pdfreader.pdf.reader.databinding.AdAdmobNativeExitLayoutBinding
import com.all.pdfreader.pdf.reader.databinding.DialogExitBinding import com.all.pdfreader.pdf.reader.databinding.DialogExitBinding
import com.google.android.gms.ads.nativead.NativeAd
import com.google.android.material.bottomsheet.BottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetDialogFragment
class ExitDialogFragment() : BottomSheetDialogFragment() { class ExitDialogFragment() : BottomSheetDialogFragment() {
@ -50,14 +45,14 @@ class ExitDialogFragment() : BottomSheetDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
setupOnClick() setupOnClick()
val cached = NativeAdCache.getAd() // val cached = NativeAdCache.getAd()
if (cached != null) { // if (cached != null) {
Log.d(AdsInsUtil.Placement.TAG, "使用缓存广告") // Log.d(AdsInsUtil.Placement.TAG, "使用缓存广告")
showNativeAd(cached) // showNativeAd(cached)
} else { // } else {
Log.d(AdsInsUtil.Placement.TAG, "无缓存,开始加载") // Log.d(AdsInsUtil.Placement.TAG, "无缓存,开始加载")
loadNativeAd() // loadNativeAd()
} // }
} }
private fun setupOnClick() { private fun setupOnClick() {
@ -67,116 +62,116 @@ class ExitDialogFragment() : BottomSheetDialogFragment() {
} }
} }
private fun showNativeAd(nativeAd: NativeAd) { // private fun showNativeAd(nativeAd: NativeAd) {
if (!isAdded || activity == null) { // if (!isAdded || activity == null) {
nativeAd.destroy() // nativeAd.destroy()
return // return
} // }
//
if (requireActivity().isFinishing || requireActivity().isDestroyed) { // if (requireActivity().isFinishing || requireActivity().isDestroyed) {
nativeAd.destroy() // nativeAd.destroy()
return // return
} // }
//
// Inflate 必须在主线程 // // Inflate 必须在主线程
val adBinding = AdAdmobNativeExitLayoutBinding.inflate(layoutInflater) // val adBinding = AdAdmobNativeExitLayoutBinding.inflate(layoutInflater)
populateNativeAdView(nativeAd, adBinding) // populateNativeAdView(nativeAd, adBinding)
//
binding.adFl.removeAllViews() // binding.adFl.removeAllViews()
binding.adFl.addView(adBinding.root) // binding.adFl.addView(adBinding.root)
} // }
private fun loadNativeAd() { private fun loadNativeAd() {
NativeAdCache.load(requireActivity(), AdsInsUtil.AdPlacement.NATIVE_AND_EXIT, onAdLoaded = { // NativeAdCache.load(requireActivity(), AdsInsUtil.AdPlacement.NATIVE_AND_EXIT, onAdLoaded = {
if (!isAdded) return@load // if (!isAdded) return@load
val ad = NativeAdCache.getAd() ?: return@load // val ad = NativeAdCache.getAd() ?: return@load
showNativeAd(ad) // showNativeAd(ad)
}) // })
} }
//
private fun populateNativeAdView( // private fun populateNativeAdView(
nativeAd: NativeAd, // nativeAd: NativeAd,
unifiedAdBinding: AdAdmobNativeExitLayoutBinding // unifiedAdBinding: AdAdmobNativeExitLayoutBinding
) { // ) {
val nativeAdView = unifiedAdBinding.root // val nativeAdView = unifiedAdBinding.root
//
// Set the media view. // // Set the media view.
nativeAdView.mediaView = unifiedAdBinding.adMedia // nativeAdView.mediaView = unifiedAdBinding.adMedia
//
// Set other ad assets. // // Set other ad assets.
nativeAdView.headlineView = unifiedAdBinding.adHeadline // nativeAdView.headlineView = unifiedAdBinding.adHeadline
nativeAdView.bodyView = unifiedAdBinding.adBody // nativeAdView.bodyView = unifiedAdBinding.adBody
nativeAdView.callToActionView = unifiedAdBinding.adCallToAction // nativeAdView.callToActionView = unifiedAdBinding.adCallToAction
nativeAdView.iconView = unifiedAdBinding.adAppIcon // nativeAdView.iconView = unifiedAdBinding.adAppIcon
// nativeAdView.priceView = unifiedAdBinding.adPrice //// nativeAdView.priceView = unifiedAdBinding.adPrice
nativeAdView.starRatingView = unifiedAdBinding.adStars // nativeAdView.starRatingView = unifiedAdBinding.adStars
// nativeAdView.storeView = unifiedAdBinding.adStore //// nativeAdView.storeView = unifiedAdBinding.adStore
nativeAdView.advertiserView = unifiedAdBinding.adAdvertiser // nativeAdView.advertiserView = unifiedAdBinding.adAdvertiser
//
// The headline and media content are guaranteed to be in every UnifiedNativeAd. // // The headline and media content are guaranteed to be in every UnifiedNativeAd.
unifiedAdBinding.adHeadline.text = nativeAd.headline // unifiedAdBinding.adHeadline.text = nativeAd.headline
nativeAd.mediaContent?.let { unifiedAdBinding.adMedia.setMediaContent(it) } // nativeAd.mediaContent?.let { unifiedAdBinding.adMedia.setMediaContent(it) }
//
// These assets aren't guaranteed to be in every UnifiedNativeAd, so it's important to // // These assets aren't guaranteed to be in every UnifiedNativeAd, so it's important to
// check before trying to display them. // // check before trying to display them.
if (nativeAd.body == null) { // if (nativeAd.body == null) {
unifiedAdBinding.adBody.visibility = View.INVISIBLE // unifiedAdBinding.adBody.visibility = View.INVISIBLE
} else {
unifiedAdBinding.adBody.visibility = View.VISIBLE
unifiedAdBinding.adBody.text = nativeAd.body
}
if (nativeAd.callToAction == null) {
unifiedAdBinding.adCallToAction.visibility = View.INVISIBLE
} else {
unifiedAdBinding.adCallToAction.visibility = View.VISIBLE
unifiedAdBinding.adCallToAction.text = nativeAd.callToAction
}
if (nativeAd.icon == null) {
unifiedAdBinding.adAppIcon.visibility = View.GONE
} else {
unifiedAdBinding.adAppIcon.setImageDrawable(nativeAd.icon?.drawable)
unifiedAdBinding.adAppIcon.visibility = View.VISIBLE
}
// if (nativeAd.price == null) {
// unifiedAdBinding.adPrice.visibility = View.INVISIBLE
// } else { // } else {
// unifiedAdBinding.adPrice.visibility = View.VISIBLE // unifiedAdBinding.adBody.visibility = View.VISIBLE
// unifiedAdBinding.adPrice.text = nativeAd.price // unifiedAdBinding.adBody.text = nativeAd.body
// } // }
// //
// if (nativeAd.store == null) { // if (nativeAd.callToAction == null) {
// unifiedAdBinding.adStore.visibility = View.INVISIBLE // unifiedAdBinding.adCallToAction.visibility = View.INVISIBLE
// } else { // } else {
// unifiedAdBinding.adStore.visibility = View.VISIBLE // unifiedAdBinding.adCallToAction.visibility = View.VISIBLE
// unifiedAdBinding.adStore.text = nativeAd.store // unifiedAdBinding.adCallToAction.text = nativeAd.callToAction
// }
//
// if (nativeAd.icon == null) {
// unifiedAdBinding.adAppIcon.visibility = View.GONE
// } else {
// unifiedAdBinding.adAppIcon.setImageDrawable(nativeAd.icon?.drawable)
// unifiedAdBinding.adAppIcon.visibility = View.VISIBLE
// }
//
//// if (nativeAd.price == null) {
//// unifiedAdBinding.adPrice.visibility = View.INVISIBLE
//// } else {
//// unifiedAdBinding.adPrice.visibility = View.VISIBLE
//// unifiedAdBinding.adPrice.text = nativeAd.price
//// }
////
//// if (nativeAd.store == null) {
//// unifiedAdBinding.adStore.visibility = View.INVISIBLE
//// } else {
//// unifiedAdBinding.adStore.visibility = View.VISIBLE
//// unifiedAdBinding.adStore.text = nativeAd.store
//// }
//
// if (nativeAd.starRating == null) {
// unifiedAdBinding.adStars.visibility = View.INVISIBLE
// } else {
// unifiedAdBinding.adStars.rating = nativeAd.starRating!!.toFloat()
// unifiedAdBinding.adStars.visibility = View.VISIBLE
// }
//
// if (nativeAd.advertiser == null) {
// unifiedAdBinding.adAdvertiser.visibility = View.INVISIBLE
// } else {
// unifiedAdBinding.adAdvertiser.text = nativeAd.advertiser
// unifiedAdBinding.adAdvertiser.visibility = View.VISIBLE
// }
//
// // This method tells the Google Mobile Ads SDK that you have finished populating your
// // native ad view with this native ad.
// nativeAdView.setNativeAd(nativeAd)
// }
//
// override fun onDestroyView() {
// super.onDestroyView()
// // 销毁广告,避免内存泄漏
// NativeAdCache.clear()
// } // }
if (nativeAd.starRating == null) {
unifiedAdBinding.adStars.visibility = View.INVISIBLE
} else {
unifiedAdBinding.adStars.rating = nativeAd.starRating!!.toFloat()
unifiedAdBinding.adStars.visibility = View.VISIBLE
}
if (nativeAd.advertiser == null) {
unifiedAdBinding.adAdvertiser.visibility = View.INVISIBLE
} else {
unifiedAdBinding.adAdvertiser.text = nativeAd.advertiser
unifiedAdBinding.adAdvertiser.visibility = View.VISIBLE
}
// This method tells the Google Mobile Ads SDK that you have finished populating your
// native ad view with this native ad.
nativeAdView.setNativeAd(nativeAd)
}
override fun onDestroyView() {
super.onDestroyView()
// 销毁广告,避免内存泄漏
NativeAdCache.clear()
}
} }

View File

@ -1,113 +0,0 @@
<com.google.android.gms.ads.nativead.NativeAdView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:minHeight="50dp"
android:orientation="vertical">
<TextView style="@style/AdAttribution" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="20dp"
android:paddingTop="3dp"
android:paddingRight="20dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/ad_app_icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:adjustViewBounds="true"
android:paddingEnd="5dp"
android:paddingRight="5dp"
android:paddingBottom="5dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/ad_headline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#0000FF"
android:textSize="16sp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/ad_advertiser"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="bottom"
android:textSize="14sp"
android:textStyle="bold" />
<RatingBar
android:id="@+id/ad_stars"
style="?android:attr/ratingBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:isIndicator="true"
android:numStars="5"
android:stepSize="0.5" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/ad_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:layout_marginRight="20dp"
android:textSize="12sp" />
<com.google.android.gms.ads.nativead.MediaView
android:id="@+id/ad_media"
android:layout_width="match_parent"
android:layout_height="175dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:orientation="horizontal"
android:paddingTop="10dp"
android:paddingBottom="10dp">
<Button
android:id="@+id/ad_call_to_action"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/bg_color"
android:gravity="center"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</com.google.android.gms.ads.nativead.NativeAdView>

View File

@ -23,9 +23,19 @@ dependencyResolutionManagement {
flatDir { flatDir {
dirs("libs") dirs("libs")
} }
// TradPlus
mavenCentral()
// Ironsource
maven("https://android-sdk.is.com/")
// Pangle
maven("https://artifact.bytedance.com/repository/pangle")
// Mintegral
//Launch GP market application Android X Version
//If you fail to pull the code using gradle, add the maven warehouse configuration to the project root build.gradle file
maven("https://dl-maven-android.mintegral.com/repository/mbridge_android_sdk_oversea")
} }
} }
rootProject.name = "PDF Reader Pro" rootProject.name = "PDF Reader Pro"
include(":app") include(":app")