ConstraintLayout 中的 MoPubRecyclerAdapter 和 Facebook 原生广告崩溃
Posted
技术标签:
【中文标题】ConstraintLayout 中的 MoPubRecyclerAdapter 和 Facebook 原生广告崩溃【英文标题】:Crash with MoPubRecyclerAdapter and Facebook Native Ads in ConstraintLayout 【发布时间】:2020-07-25 13:06:38 【问题描述】:预期
MoPubRecyclerAdapter
预计会使用定义的 ConstraintLayout
扩充原生 Facebook RecyclerView
单元格。
观察到
错误
对于由 Facebook 原生广告创建的 ConstraintLayout
s,MoPubRecyclerAdapter
会间歇性崩溃。此问题已在 MoPub SDK forum 和 MoPub android Mediation GitHub 存储库中记录。
日志
Fatal Exception: java.lang.ClassCastException: androidx.constraintlayout.widget.ConstraintLayout cannot be cast to android.widget.RelativeLayout
at com.mopub.nativeads.FacebookAdRenderer$FacebookNativeViewHolder.fromViewBinder(FacebookAdRenderer.java:139)
at com.mopub.nativeads.FacebookAdRenderer.renderAdView(FacebookAdRenderer.java:58)
at com.mopub.nativeads.FacebookAdRenderer.renderAdView(FacebookAdRenderer.java:28)
at com.mopub.nativeads.NativeAd.renderAdView(NativeAd.java:166)
at com.mopub.nativeads.MoPubStreamAdPlacer.bindAdView(MoPubStreamAdPlacer.java:433)
at com.mopub.nativeads.MoPubRecyclerAdapter.onBindViewHolder(MoPubRecyclerAdapter.java:424)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6781)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6823)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5752)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6019)
at androidx.recyclerview.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:286)
at androidx.recyclerview.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:343)
at androidx.recyclerview.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:359)
at androidx.recyclerview.widget.GapWorker.prefetch(GapWorker.java:366)
at androidx.recyclerview.widget.GapWorker.run(GapWorker.java:397)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:205)
at android.app.ActivityThread.main(ActivityThread.java:6991)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:884)
实施
facebook_native_ad_item.xml
<?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:id="@+id/native_outer_view"
style="@style/AdContentCardStyle"
android:layout_
android:layout_
android:textDirection="locale">
<TextView
android:id="@+id/native_title"
style="@style/CellCreatorStyle"
app:layout_constraintBottom_toBottomOf="@+id/guideline"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/native_icon_image" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_
android:layout_
android:orientation="horizontal"
app:layout_constraintBottom_toTopOf="@id/native_media_view"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/sponsored"
android:layout_
android:layout_
android:text="@string/sponsored"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/guideline" />
<com.facebook.ads.AdIconView
android:id="@+id/native_icon_image"
android:layout_
android:layout_
android:paddingRight="@dimen/padding_tiny"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.facebook.ads.MediaView
android:id="@+id/native_media_view"
style="@style/AdCellPreviewImageStyle"
android:contentDescription="@string/native_main_image"
app:layout_constraintBottom_toTopOf="@id/native_text"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/sponsored" />
<TextView
android:id="@+id/native_text"
style="@style/CellTitleStyle"
app:layout_constraintBottom_toTopOf="@id/native_cta"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/native_media_view"
tools:text="@string/learn_more" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/native_ad_choices_relative_layout"
android:layout_
android:layout_
android:gravity="left"
app:layout_constraintBottom_toBottomOf="@id/native_cta"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="@id/native_cta" />
<TextView
android:id="@+id/native_cta"
style="@style/NativeCtaStyle"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/native_text"
tools:text="@string/learn_more" />
</androidx.constraintlayout.widget.ConstraintLayout>
SomeFragment.kt
adapter = FeedAdapter(feedViewModel, viewEvent)
moPubAdapter = MoPubRecyclerAdapter(
requireActivity(),
adapter,
MoPubNativeAdPositioning.MoPubServerPositioning())
moPubAdapter.registerAdRenderer(FacebookAdRenderer(
FacebookViewBinder.Builder(fb_native_ad_item)
.titleId(native_title)
.textId(native_text)
.mediaViewId(native_media_view)
.adIconViewId(native_icon_image)
.adChoicesRelativeLayoutId(native_ad_choices_relative_layout)
.advertiserNameId(native_title)
.callToActionId(native_cta)
.build()))
val viewBinder = ViewBinder.Builder(native_ad_item)
.titleId(native_title)
.textId(native_text)
.mainImageId(R.id.native_main_image)
.iconImageId(native_icon_image)
.callToActionId(native_cta)
.privacyInformationIconImageId(string.native_privacy_information_icon_image)
.build()
moPubAdapter.registerAdRenderer(FlurryNativeAdRenderer(FlurryViewBinder(Builder(viewBinder))))
moPubAdapter.registerAdRenderer(MoPubVideoNativeAdRenderer(
MediaViewBinder.Builder(fb_native_ad_item)
.mediaLayoutId(native_media_view)
.iconImageId(native_icon_image)
.titleId(native_title)
.textId(native_text)
.privacyInformationIconImageId(native_ad_choices_relative_layout)
.build()))
moPubAdapter.registerAdRenderer(MoPubStaticNativeAdRenderer(viewBinder))
moPubAdapter.setContentChangeStrategy(MOVE_ALL_ADS_WITH_CONTENT)
contentRecyclerView.adapter = moPubAdapter
FeedApater.kt
@ExperimentalCoroutinesApi
class FeedAdapter(val viewModel: FeedViewModel, val viewEvent: FeedViewEvent)
: PagedListAdapter<Content, FeedAdapter.ViewHolder>(DIFF_CALLBACK)
class ViewHolder(private var binding: CellContentBinding) : RecyclerView.ViewHolder(binding.root)
fun bind(viewModel: FeedViewModel, content: Content, onClickListener: OnClickListener)
binding.viewModel = viewModel
binding.data = content
binding.clickListener = onClickListener
binding.executePendingBindings()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder
val inflater = LayoutInflater.from(parent.context)
val binding = CellContentBinding.inflate(inflater, parent, false)
return ViewHolder(binding)
override fun onBindViewHolder(holder: ViewHolder, position: Int)
getItem(position)?.let content ->
holder.bind(viewModel, content, createOnClickListener(content, position))
private fun createOnClickListener(content: Content, position: Int) = OnClickListener view ->
环境
库
implementation("com.mopub:mopub-sdk-native-static:5.11.1@aar") transitive = true
implementation("com.mopub:mopub-sdk-native-video:5.11.1@aar") transitive = true
implementation 'com.facebook.android:audience-network-sdk:5.1.0'
implementation 'com.mopub.mediation:facebookaudiencenetwork:5.1.0.0'
implementation 'com.flurry.android:ads:12.1.0@aar'
implementation 'com.flurry.android:analytics:12.1.0@aar'
implementation 'com.mopub.mediation:flurry:11.4.0.0'
Android 级别
8.1.0 9 10设备
LG Q60 像素 3a 红米 Note 5 Pro尝试的解决方案
MoPub SDK 的库版本已更新为5.12.0
,Facebook Audience Network 更新为5.8.0
,Facebook 中介更新为5.8.0.0
。是否能解决上述崩溃问题,有待确定。
implementation("com.mopub:mopub-sdk-native-static:5.12.0") transitive = true
implementation("com.mopub:mopub-sdk-native-video:5.12.0") transitive = true
implementation 'com.facebook.android:audience-network-sdk:5.8.0'
implementation 'com.mopub.mediation:facebookaudiencenetwork:5.8.0.0'
【问题讨论】:
【参考方案1】:使用RelativeLayout
而不是ConstraintLayout
正如 MoPub 的工程师在此 GitHub issue 中指出的那样,Facebook 中介尚不兼容 ConstraintLayout
。
由于 Facebook Audience Network SDK 4.99.0+ 版本的内部更改,AdChoices 图标 XML 视图(ID 为
native_ad_choices_relative_layout
)需要为RelativeLayout
。适配器在这里需要RelativeLayout
。
之前
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/native_ad_choices_relative_layout"
android:layout_
android:layout_
android:gravity="left"
app:layout_constraintBottom_toBottomOf="@id/native_cta"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="@id/native_cta" />
之后
<RelativeLayout
android:id="@+id/native_ad_choices_relative_layout"
android:layout_
android:layout_
android:gravity="left" />
文档:Setup Ad Renderers for Native Ads
示例:github.com/mopub/mopub-sdk-android
【讨论】:
以上是关于ConstraintLayout 中的 MoPubRecyclerAdapter 和 Facebook 原生广告崩溃的主要内容,如果未能解决你的问题,请参考以下文章
MoPub #withMediatedNetworkConfiguration 解释
如何使用适用于 iOS 的 Admob (google) 设置 MoPub 中介?