我正在尝试在 Jetpack Compose 中实施
InterstitialAd
。这是我的AdsHelpder.kt
课:
class AdsHelper(private val context: Context) : FullScreenContentCallback() {
private var onAdDismissed: (() -> Unit)? = null
private var interstitialAd: InterstitialAd? = null
private val adRequest = AdRequest.Builder().build()
fun onDestroy() {
interstitialAd?.fullScreenContentCallback = null
interstitialAd = null
}
fun onLoadInterstitialAd(canLoad: Boolean) {
val id = context.onString(R.string.interstitial_ad_id)
if (canLoad) {
InterstitialAd.load(context, id, adRequest, object : InterstitialAdLoadCallback() {
override fun onAdLoaded(p0: InterstitialAd) {
interstitialAd = p0
}
override fun onAdFailedToLoad(p0: LoadAdError) {
interstitialAd = null
}
})
}
}
override fun onAdDismissedFullScreenContent() {
interstitialAd = null
onAdDismissed?.invoke()
}
fun onShowInterstitialAd(onAdDismissed: () -> Unit) {
interstitialAd?.apply {
show(context.onMainActivity())
fullScreenContentCallback = this@AdsHelper
}
this.onAdDismissed = onAdDismissed
}
override fun onAdFailedToShowFullScreenContent(e: AdError) {
interstitialAd = null
}
}
由于我需要在多个屏幕上显示 InterstitialAd,我认为这种实现方式看起来最适合
MainActivity.kt
:
class MainActivity : ComponentActivity() {
private lateinit var data: Data
private var adsHelper: AdsHelper? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
data = ViewModelProvider(this)[Data::class.java]
adsHelper = AdsHelper(this)
setContent {
AppTheme {
val controller = rememberAnimatedNavController()
controller.addOnDestinationChangedListener { _, route, _ ->
adsHelper?.onLoadInterstitialAd(route != HOME)
}
LaunchedEffect(data.interstitial) {
when {
data.interstitial -> adsHelper?.onShowInterstitialAd {
data.interstitial = false
}
}
}
Column {
Scaffold(
Modifier.weight(1f)
) {
NavGraph(controller, data)
}
}
}
}
}
override fun onDestroy() {
adsHelper?.onDestroy()
super.onDestroy()
}
}
这里
Data.kt
:
class Data(app: Application) : AndroidViewModel(app) {
var interstitial by mutableStateOf(false)
}
我可以在
MainActivity.kt
中避免这些行
...
controller.addOnDestinationChangedListener { _, route, _ ->
adsHelper?.onLoadInterstitialAd(route != HOME)
}
...
然后直接调用
adsHelper?.onLoadInterstitialAd(true)
,但是会导致无穷无尽的日志:
...
D/CCodecConfig: c2 config diff is c2::u32 default.color.matrix = 1
c2::u32 default.color.primaries = 1
c2::u32 default.color.range = 2
c2::u32 default.color.transfer = 3
c2::u32 raw.max-size.height = 360
c2::u32 raw.max-size.width = 640
c2::u32 raw.size.height = 360
c2::u32 raw.size.width = 640
W/Codec2Client: query -- param skipped: index = 1107298332.
D/CCodec: client requested max input size 86400, which is smaller than what component recommended (6291456); overriding with component recommendation.
W/CCodec: This behavior is subject to change. It is recommended that app developers double check whether the requested max input size is in reasonable range.
D/CCodec: encoding statistics level = 0
D/CCodec: setup formats input: AMessage(what = 0x00000000) = {
int32_t height = 360
int32_t level = 256
int32_t max-input-size = 6291456
string mime = "video/x-vnd.on2.vp9"
int32_t profile = 1
int32_t width = 640
Rect crop(0, 0, 639, 359)
}
D/CCodec: setup formats output: AMessage(what = 0x00000000) = {
int32_t android._color-format = 2135033992
int32_t android._video-scaling = 1
Rect crop(0, 0, 639, 359)
int32_t color-standard = 1
int32_t color-range = 2
int32_t color-transfer = 3
Buffer hdr10-plus-info = {
}
int32_t height = 360
int32_t max-height = 360
int32_t max-width = 640
string mime = "video/raw"
int32_t rotation-degrees = 0
int32_t sar-height = 1
int32_t sar-width = 1
int32_t width = 640
int32_t android._dataspace = 260
int32_t color-format = 2130708361
}
I/CCodecConfig: query failed after returning 11 values (BAD_INDEX)
W/Codec2Client: query -- param skipped: index = 1107298332.
D/CCodec: client requested max input size 86400, which is smaller than what component recommended (6291456); overriding with component recommendation.
W/CCodec: This behavior is subject to change. It is recommended that app developers double check whether the requested max input size is in reasonable range.
D/CCodec: encoding statistics level = 0
D/CCodec: setup formats input: AMessage(what = 0x00000000) = {
int32_t height = 360
int32_t level = 256
int32_t max-input-size = 6291456
string mime = "video/x-vnd.on2.vp9"
int32_t profile = 1
int32_t width = 640
Rect crop(0, 0, 639, 359)
}
D/CCodec: setup formats output: AMessage(what = 0x00000000) = {
int32_t android._color-format = 2135033992
int32_t android._video-scaling = 1
Rect crop(0, 0, 639, 359)
int32_t color-standard = 1
int32_t color-range = 2
int32_t color-transfer = 3
Buffer hdr10-plus-info = {
}
int32_t height = 360
int32_t max-height = 360
int32_t max-width = 640
string mime = "video/raw"
int32_t rotation-degrees = 0
int32_t sar-height = 1
int32_t sar-width = 1
int32_t width = 640
int32_t android._dataspace = 260
int32_t color-format = 2130708361
}
I/CCodecConfig: query failed after returning 11 values (BAD_INDEX)
D/MediaCodec: keep callback message for reclaim
D/MediaCodec: keep callback message for reclaim
W/Codec2Client: query -- param skipped: index = 1342179345.
W/Codec2Client: query -- param skipped: index = 2415921170.
W/Codec2Client: query -- param skipped: index = 1342179345.
W/Codec2Client: query -- param skipped: index = 2415921170.
W/Codec2Client: query -- param skipped: index = 2684356609.
W/Codec2Client: query -- param skipped: index = 2684356609.
D/CCodecBufferChannel: [c2.goldfish.vp9.decoder#948] Created input block pool with allocatorID 16 => poolID 60 - OK (0)
D/CCodecBufferChannel: [c2.goldfish.vp9.decoder#415] Created input block pool with allocatorID 16 => poolID 59 - OK (0)
D/CCodecBufferChannel: [c2.goldfish.vp9.decoder#948] Query output surface allocator returned 0 params => BAD_INDEX (6)
D/CCodecBufferChannel: [c2.goldfish.vp9.decoder#415] Query output surface allocator returned 0 params => BAD_INDEX (6)
I/CCodecBufferChannel: [c2.goldfish.vp9.decoder#415] Created output block pool with allocatorID 18 => poolID 151 - OK
I/CCodecBufferChannel: [c2.goldfish.vp9.decoder#948] Created output block pool with allocatorID 18 => poolID 152 - OK
D/CCodecBufferChannel: [c2.goldfish.vp9.decoder#415] Configured output block pool ids 151 => OK
D/CCodecBufferChannel: [c2.goldfish.vp9.decoder#948] Configured output block pool ids 152 => OK
D/Codec2-OutputBufferQueue: remote graphic buffer migration 0/0
D/Codec2-OutputBufferQueue: remote graphic buffer migration 0/0
D/Codec2Client: setOutputSurface -- failed to set consumer usage (6/BAD_INDEX)
D/Codec2Client: setOutputSurface -- generation=9693208 consumer usage=0x900
D/Codec2Client: setOutputSurface -- failed to set consumer usage (6/BAD_INDEX)
D/Codec2Client: setOutputSurface -- generation=9693207 consumer usage=0x900
D/Codec2Client: Surface configure completed
D/Codec2Client: Surface configure completed
I/DynamiteModule: Considering local module com.google.android.gms.ads.dynamite:0 and remote module com.google.android.gms.ads.dynamite:230500000
I/DynamiteModule: Selected remote version of com.google.android.gms.ads.dynamite, version >= 230500000
D/CCodecConfig: c2 config diff is c2::u32 raw.channel-mask.value = 12
D/CCodecBuffers: [c2.android.aac.decoder#912:Output[N]] popFromStashAndRegister: at 1000000000000us, output format changed to AMessage(what = 0x00000000) = {
int32_t aac-drc-album-mode = 0
int32_t aac-drc-boost-level = 127
int32_t aac-drc-cut-level = 127
int32_t aac-drc-effect-type = 3
int32_t aac-drc-output-loudness = -1
int32_t aac-encoded-target-level = -1
int32_t aac-max-output-channel_count = 8
int32_t aac-target-ref-level = 64
int32_t channel-count = 2
int32_t channel-mask = 12
int32_t max-output-channel-count = 8
string mime = "audio/raw"
int32_t sample-rate = 44100
int32_t android._config-pcm-encoding = 2
}
D/CCodecConfig: c2 config diff is c2::u32 raw.crop.height = 360
c2::u32 raw.crop.left = 0
c2::u32 raw.crop.top = 0
c2::u32 raw.crop.width = 640
D/CCodecConfig: c2 config diff is c2::u32 raw.channel-mask.value = 12
D/CCodecBuffers: [c2.android.aac.decoder#806:Output[N]] popFromStashAndRegister: at 1000000000000us, output format changed to AMessage(what = 0x00000000) = {
int32_t aac-drc-album-mode = 0
int32_t aac-drc-boost-level = 127
int32_t aac-drc-cut-level = 127
int32_t aac-drc-effect-type = 3
int32_t aac-drc-output-loudness = -1
int32_t aac-encoded-target-level = -1
int32_t aac-max-output-channel_count = 8
int32_t aac-target-ref-level = 64
int32_t channel-count = 2
int32_t channel-mask = 12
int32_t max-output-channel-count = 8
string mime = "audio/raw"
int32_t sample-rate = 44100
int32_t android._config-pcm-encoding = 2
}
I/DynamiteModule: Considering local module com.google.android.gms.ads.dynamite:0 and remote module com.google.android.gms.ads.dynamite:230500000
I/DynamiteModule: Selected remote version of com.google.android.gms.ads.dynamite, version >= 230500000
V/FA: Inactivity, disconnecting from the service
D/BufferPoolAccessor2.0: evictor expired: 4, evicted: 4
I/DynamiteModule: Considering local module com.google.android.gms.ads.dynamite:0 and remote module com.google.android.gms.ads.dynamite:230500000
I/DynamiteModule: Selected remote version of com.google.android.gms.ads.dynamite, version >= 230500000
I/DynamiteModule: Considering local module com.google.android.gms.ads.dynamite:0 and remote module com.google.android.gms.ads.dynamite:230500000
I/DynamiteModule: Selected remote version of com.google.android.gms.ads.dynamite, version >= 230500000
D/CCodecConfig: c2 config diff is c2::u32 raw.crop.height = 360
c2::u32 raw.crop.left = 0
c2::u32 raw.crop.top = 0
c2::u32 raw.crop.width = 640
D/BufferPoolAccessor2.0: evictor expired: 1, evicted: 1
I/Ads: This request is sent from a test device.
...
此外,在生成这些日志时,特别是显示
InterstitialAd
(当 data.interstitial = true
时),应用程序变慢/冻结。
这就是为什么我决定只在目标屏幕上加载
InterstitialAd
,在本例中是HOME
旁边的所有屏幕。但这并不能解决问题,并且日志不断加载。
此外,根据
Crashlytics
和App Quality Insights
会出现TransactionTooLargeException
。
但是应用程序不会崩溃,只会冻结到data.interstitial = false
。之后应用程序运行正常。
很明显,加载和显示
InterstitialAd
会消耗大量资源/内存,尤其是在有视频广告的情况下。
我最近开始使用 Jetpack Compose,很多东西对我来说都是新的。因此,我的实施可能是错误的,并不是真正最优的。
知道哪里出了问题以及我做错了什么会很有帮助。
非常感谢。