You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Android原生广告报错找不到id为homeScreen的NativeAdFactory

Flutter Android端原生广告加载报错:Can't find NativeAdFactory with id: homeScreen

报错信息

PlatformException(NativeAdError, Can't find NativeAdFactory with id: homeScreen, null, null)

环境信息

使用的google_mobile_ads插件版本:

google_mobile_ads: ^0.13.0

现有代码实现

HomeScreenNativeAd.kt 原生广告工厂实现

class HomeScreenNativeAd(val context: Context) : GoogleMobileAdsPlugin.NativeAdFactory {

    override fun createNativeAd(
            nativeAd: NativeAd,
            customOptions: MutableMap<String, Any>?
    ): NativeAdView {
        val homeScreenNativeView = LayoutInflater.from(context)
                .inflate(R.layout.home_screen_native_ad, null) as NativeAdView

        with(homeScreenNativeView) {
            val attributionViewSmall =
                    findViewById<TextView>(R.id.tv_home_item_native_ad_attribution_small)


            val icon = findViewById<ImageView>(R.id.home_item_bg_image)


            val image = nativeAd.icon
            if (image != null) {
                attributionViewSmall.visibility = View.VISIBLE
                icon.setImageDrawable(image.drawable)
            } else {
                attributionViewSmall.visibility = View.INVISIBLE
            }
            this.iconView = iconView

            val adV =   findViewById<TextView>(R.id.adviser)
            adV.text = nativeAd.advertiser
            this.advertiserView =adV

            val ctaButton =   findViewById<TextView>(R.id.home_screen_cta_button)
            ctaButton.text = nativeAd.callToAction
            this.callToActionView = ctaButton

            val adDesc =   findViewById<TextView>(R.id.home_item_ad_desc)
            adDesc.text = nativeAd.body
            this.bodyView = ctaButton



            val headlineView = findViewById<TextView>(R.id.home_item_ad_title)
            headlineView.text = nativeAd.headline
            this.headlineView = headlineView




            setNativeAd(nativeAd)
        }

        return homeScreenNativeView
    }
}

home_screen_native_ad.xml 广告布局文件

<com.google.android.gms.ads.nativead.NativeAdView
    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="match_parent">
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <RelativeLayout
            android:orientation="vertical"
            android:layout_width="wrap_content"
            android:layout_height="160dp">
            <FrameLayout
                android:layout_width="match_parent"
                android:background="#00ffffff"
                android:layout_height="140dp"/>
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="190dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="16dp"
                android:layout_marginBottom="16dp"
                android:gravity="start"
                android:orientation="horizontal">
                <ImageView
                    android:id="@+id/home_item_bg_image"
                    android:layout_width="60dp"
                    android:layout_height="60dp"
                    android:scaleType="centerCrop"
                    android:layout_marginLeft="16dp"/>
                <TextView
                    android:id="@+id/home_item_ad_title"
                    android:layout_width="220dp"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="10dp"
                    android:layout_toRightOf="@+id/home_item_bg_image"
                    android:ellipsize="end"
                    android:lines="1"
                    android:maxLines="1"
                    android:textColor="#FFFFFFFF"
                    android:textSize="20sp"
                    tools:text="Headline" />
                <TextView
                    android:id="@+id/adviser"
                    android:layout_width="229dp"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="10dp"
                    android:layout_marginTop="32dp"
                    android:layout_toRightOf="@+id/home_item_bg_image"
                    android:ellipsize="end"
                    android:lines="1"
                    android:maxLines="1"
                    android:textColor="#FFFFFFFF"
                    android:textSize="14sp"
                    tools:text="Advertiser" />
                <TextView
                    android:id="@+id/tv_home_item_native_ad_attribution_small"
                    android:layout_width="35dp"
                    android:layout_height="20dp"
                    android:layout_marginLeft="10dp"
                    android:layout_toRightOf="@+id/home_item_ad_title"
                    android:background="@color/softOrange"
                    android:gravity="center"
                    android:lines="1"
                    android:maxLines="1"
                    android:text="Ad"
                    android:textColor="#FFFF"
                    android:textSize="12sp" />
            </RelativeLayout>
            <TextView
                android:id="@+id/home_item_ad_desc"
                android:layout_width="270dp"
                android:layout_height="40dp"
                android:layout_marginTop="85dp"
                android:ellipsize="end"
                android:lines="2"
                android:gravity="center_vertical"
                android:maxLines="2"
                android:textColor="#FFFFFFFF"
                android:textSize="14sp"
                android:layout_marginLeft="16dp"
                tools:text="Headline" />
            <TextView
                android:id="@+id/home_screen_cta_button"
                android:layout_width="wrap_content"
                android:layout_marginLeft="10dp"
                android:layout_height="30dp"
                android:layout_toRightOf="@+id/home_item_ad_desc"
                android:layout_marginTop="100dp"
                android:text="INSTALL"
                android:gravity="center"
                android:ellipsize="end"
                android:lines="1"
                android:textColor="#FFF"
                android:maxLines="1"
                android:textSize="18sp"/>
        </RelativeLayout>
    </FrameLayout>
</com.google.android.gms.ads.nativead.NativeAdView>

MainActivity.kt 注册逻辑

class MainActivity : FlutterActivity() {
    private val CHANNEL = "verified.cv/channel" // 与main.dart中设置的渠道名一致

    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
            call, result ->
            if (call.method == "createNotificationChannel") {
                val argData = call.arguments as java.util.HashMap<String, String>
                val completed = createNotificationChannel(argData)
                if (completed == true) {
                    result.success(completed)
                } else {
                    result.error("Error Code", "Error Message", null)
                }
            } else {
                result.notImplemented()
            }
        }
        GoogleMobileAdsPlugin.registerNativeAdFactory(
                flutterEngine, "listTile", ListTileNativeAdFactory(context))
        GoogleMobileAdsPlugin.registerNativeAdFactory(
                flutterEngine, "skillCard", SkillCardNativeFactory(context))
        GoogleMobileAdsPlugin.registerNativeAdFactory(
                flutterEngine, "homeScreen", HomeScreenNativeAd(context))
        GoogleMobileAdsPlugin.registerNativeAdFactory(
                flutterEngine, "feedItem", FeedItemNativeFactory(context))
    }

    override fun cleanUpFlutterEngine(flutterEngine: FlutterEngine) {
        super.cleanUpFlutterEngine(flutterEngine)
        GoogleMobileAdsPlugin.unregisterNativeAdFactory(flutterEngine, "listTile")
        GoogleMobileAdsPlugin.unregisterNativeAdFactory(flutterEngine, "skillCard")
        GoogleMobileAdsPlugin.unregisterNativeAdFactory(flutterEngine, "homeScreen")
        GoogleMobileAdsPlugin.unregisterNativeAdFactory(flutterEngine, "feedItem")
    }

    private fun createNotificationChannel(mapData: HashMap<String, String>): Boolean {
        val completed: Boolean
        if (VERSION.SDK_INT >= VERSION_CODES.O) {
            val id = mapData["id"]
            val name = mapData["name"]
            val descriptionText = mapData["description"]
            val importance = NotificationManager.IMPORTANCE_HIGH
            val mChannel = NotificationChannel(id, name, importance)
            mChannel.description = descriptionText
            val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(mChannel)
            completed = true
        } else {
            completed = false
        }
        return completed
    }
}

错误日志

I/flutter ( 1409): ----------------FIREBASE CRASHLYTICS----------------
I/flutter ( 1409): PlatformException(NativeAdError, Can't find NativeAdFactory with id: homeScreen, null, null)
I/flutter ( 1409): #0      StandardMethodCodec.decodeEnvelope
package:flutter/…/services/message_codecs.dart:607
I/flutter ( 1409): #1      MethodChannel._invokeMethod
package:flutter/…/services/platform_channel.dart:177
I/flutter ( 1409): <asynchronous suspension>
I/flutter ( 1409): #2      NativeAd.load
package:google_mobile_ads/src/ad_containers.dart:1033
I/flutter ( 1409): <asynchronous suspension>
I/flutter ( 1409): ----------------------------------------------------
D/ACodec  ( 1409): dataspace changed to 0x10c40000 (R:2(Limited), P:4(BT601_6_525), M:3(BT601_6), T:3(SMPTE170M))

排查解决步骤

  • 检查Dart端广告初始化的factoryId一致性
    确认Dart侧创建NativeAd实例时传入的factoryId参数完全等于"homeScreen",注意大小写、前后空格都不能有差异,这是最高发的低级错误。
  • 检查注册时机问题
    你当前在configureFlutterEngine中注册的位置是正确的,但如果应用使用了多FlutterEngine、或者广告在FlutterEngine完全初始化前就触发加载,会出现注册未完成就查找工厂的情况。可以在注册homeScreen工厂的位置加日志打印,确认广告加载前注册逻辑已经执行。
  • 修复代码里的变量赋值错误
    你的HomeScreenNativeAd.kt里有两处明显的赋值错误,会导致广告工厂初始化崩溃,插件捕获异常后会直接返回找不到工厂的错误:
    • 第一处:你定义了val icon = findViewById<ImageView>(R.id.home_item_bg_image),但后面赋值时写的是this.iconView = iconView,这里iconView未定义,应该改成this.iconView = icon
    • 第二处:你给广告描述赋值时写的是this.bodyView = ctaButton,错误地把按钮控件赋值给了正文视图,应该改成this.bodyView = adDesc
  • 检查混淆规则
    如果是release包出现该问题,需要在proguard规则里添加以下配置,防止广告工厂类被混淆:
    -keep class com.google.android.gms.ads.** { *; }
    -keep class * extends com.google.android.gms.ads.GoogleMobileAdsPlugin.NativeAdFactory { *; }
    
  • 清理缓存重新构建
    执行flutter clean后重新运行应用,避免旧的构建缓存导致代码修改不生效。

额外提示:你当前使用的google_mobile_ads 0.13.0是非常旧的版本,修复完上述问题后建议升级到官方稳定版,旧版本本身存在不少原生广告注册的已知bug。


内容的提问来源于stack exchange,提问作者Mehmet Kamay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 10:27:08