# Flutter 的原生广告服务集成

> 使用 LevelPlay SDK 将原生广告服务集成到 Flutter app程序中，提供预定义和自定义的广告自定制化/自定义模板。

原生广告服务是一种可以自定义的广告形式，可与 app 中的其他内容混合。这使得广告服务看起来更有机，从而带来更好的用户体验和更高的留存率。

## 先决条件##prerequisites

确保已将 LevelPlay Flutter Plug-in 8.4.0+ 正确[集成](/grow/levelplay/sdk/flutter/plugin-integration.md)到应用程序中。

## 集成 LevelPlay 原生广告服务##integrate-levelplay-native-ads

使用 Flutter 插件集成 LevelPlay 原生广告服务有两种方法：

* 原生模板：插件以 XML 和 XIB 文件格式提供的预定义模板
* 自定义模板：由开发者设计样式的模板

## 原生模板##native-templates

原生模板是实现原生广告逻辑的预定视图图。此设置会在广告加载后处理视图数量，并在广告销毁后清除它们。

有两个模板选项：

* Small：不包含媒体视图的模板。
* 中等：具有媒体视图功能的模板。

虽然样式大致相似，但您也可以根据自己的偏好进行自定义。

要集成原生模板，请完成以下步骤。

### 创建 LevelPlayNativeAd 对象##create-levelplaynativead-object

创建一个 `LevelPlayNativeAd` 对象，负责将广告加载到 `LevelPlayNativeAdView` 容器中。此对象将处理广告方法，例如加载、销毁，并将为事件回调定义广告放置/位置和监听器。

```dart
_nativeAd = LevelPlayNativeAd.builder()
        .withPlacementName([YOUR_PLACEMENT])
        .withListener([YOUR_LEVEL_PLAY_NATIVE_AD_LISTENER])
        .build();

```

### 实现监听器##implement-the-listener

在代码中实现这些`LevelPlayNativeAdListener`。LevelPlay SDK 会触发多个回调来通知您原生广告活动。SDK 将通知监听器以下所有事件：

```dart
/**
 在点击原生广告后调用。
 @param nativeAd Level 播放原生广告。
 @param adInfo 广告的信息。
 */ 
@override
void onAdClicked(LevelPlayNativeAd? nativeAd, IronSourceAdInfo? adInfo) {}
/**
 在记录原生广告展示后调用。
 @param nativeAd Level 播放原生广告。
 @param adInfo 广告的信息。
 */
 @override
 void onAdImpression(LevelPlayNativeAd? nativeAd, IronSourceAdInfo? adInfo) {}
/**
 在本机尝试加载广告但失败后调用。
 @param nativeAd Level 播放原生广告。
 @param 报错 报错原因
 */  
@override
void onAdLoadFailed(LevelPlayNativeAd? nativeAd, IronSourceError? error) {}
/**
 成功加载原生广告后调用
 @param nativeAd Level 播放原生广告。
 @param adInfo 广告的信息。
 */
@override
void onAdLoaded(LevelPlayNativeAd? nativeAd, IronSourceAdInfo? adInfo) {}

```

### 创建 LevelPlayNativeAdView##create-levelplaynativeadview

创建一个 `LevelPlayNativeAdView` 小部件来定义将托管加载的原生广告的容器。此对象将通过确定宽度和高度或设置容器的框约束来定义原生广告边界。它还可以处理原生广告元素样式，例如：作品/游戏作品、正文、广告主和号召行动按钮。

对于原生模板，默认类型为 `SMALL`，可通过在创建小部件时定义模板类型来更改。 

```dart
LevelPlayNativeAdView(
          height：350，// Medium Type 的建议高度
          width：300, // Medium Type 的建议宽度
          nativeAd: _nativeAd,
          onPlatformViewCreated: () {
            _nativeAd?.loadAd(); // Recommeneded place to loadAd
          },
          templateType：LevelPlayTemplateType.MEDIUM、
          templateStyle：[LevelPlayNativeAdTemplateStyle] 可选
)
LevelPlayNativeAdView(
          height：175, // Small Type 的建议高度
          width：300, // Small Type 的建议宽度
          nativeAd: _nativeAd,
          onPlatformViewCreated: () {
            _nativeAd?.loadAd(); // Recommeneded place to loadAd
          },
          templateType：LevelPlayTemplateType.SMALL、
          templateStyle：[LevelPlayNativeAdTemplateStyle] 可选
)

```

### 加载广告##load-the-ad

调用 loadAd 加载原生广告。可以在收到原生广告视图容器的`onPlatformViewCreated`回调后或在开发者决定的另一个时间调用此方法。

```dart
_nativeAd?.loadAd();

```

### 销毁原生广告##destroy-the-native-ad

要销毁原生广告，请调用以下方法：

```dart
  _nativeAd?.destroyAd();

```

无法再加载已销毁的原生广告。如果要再次投放广告，必须重新创建广告容器小部件。

## 自定义模板##custom-templates

自定义模板允许您设计自己的样式和功能来满足指定的需求。它们提供个性化布局和功能的灵活性，确保独特的用户体验。

这些模板主要用于需要对广告设计进行更高级别的控制。它可以在 Android 和 iOS 平台上实现，并且需要额外的代码实现。

要创建自定义模板，您需要编写原生代码并开发自己的自定义布局。按照以下步骤进行集成：

### 创建 NativeAdViewFactory##create-nativeadviewfactory

扩展 LevelPlayNativeAdView类 类的 Android 或 iOS 实现将使用自定布局显示加载的广告。

#### Android##android

```kotlin
// Android Implementation 
import com.ironSource.ironsource_mediation.LevelPlayNativeAdViewFactory
导入 Android.widget.按钮
导入 Android.widget.ImageView
import Android
import com.ironsource.mediationsdk.ads.nativead.LevelPlayMediaView
import com.ironsource.mediationsdk.ads.nativead.LevelPlayNativeAd
import com.ironsource.mediationsdk.ads.nativead.NativeAdLayout
import io.flutter.plugin.common.BinaryMessenger
/**
 * 类是如何实现自定义原生广告的示例。
 * 类必须接收 BinaryMessenger 和
 * 开发者要加载的原生广告布局。它还
 * 必须扩展 LevelPlayNativeAdViewFactory 并覆盖
 * 方法 bindNativeAdToView 以便使用 填充视图
 * 加载的原生广告。
 */
class NativeAdViewFactoryExample(
    levelPlayBinaryMessenger:BinaryMessenger,
    layoutId:Int
) :LevelPlayNativeAdViewFactory(levelPlayBinaryMessenger, layoutId) {
    覆盖 fun bindNativeAdToView(nativeAd:LevelPlayNativeAd?、nativeAdLayout：NativeAdLayout) {
        // Extract views
        val titleView = nativeAdLayout.findViewById<TextView>(R.id.adTitle)
        val bodyView = nativeAdLayout.findViewById<TextView>(R.id.adBody)
        val advertiserView = nativeAdLayout.findViewById<TextView>(R.id.adAdvertiser)
        val callToActionView = nativeAdLayout.findViewById<Button>(R.id.adCallToAction)
        val iconView = nativeAdLayout.findViewById<ImageView>(R.id.adAppIcon)
        val mediaView = nativeAdLayout.findViewById<LevelPlayMediaView>(R.id.adMedia)
        // Bind native ad to view
        if (nativeAd != null) {
            if (nativeAd.title != null) {
                titleView.text = nativeAd.title
                nativeAdLayout.setTitleView(titleView)
            }
            if (nativeAd.body != null) {
                bodyView.text = nativeAd.body
                nativeAdLayout.setBodyView(bodyView)
            }
            if (nativeAd.advertiser != null) {
                advertiserView.text = nativeAd.advertiser
                nativeAdLayout.setAdvertiserView(advertiserView)
            }
            if (nativeAd.callToAction != null) {
                callToActionView.text = nativeAd.callToAction
                nativeAdLayout.setCallToActionView(callToActionView)
            }
            if (nativeAd.icon != null) {
                iconView!!.setImageDrawable(nativeAd.icon!!.drawable)
                nativeAdLayout.setIconView(iconView)
            }
            if (mediaView != null) {
                nativeAdLayout.setMediaView(mediaView)
            }
            nativeAdLayout.registerNativeAdViews(nativeAd)
        }
    }
}

```

#### iOS##ios

```objc
// iOS Implementation
/// h file
#import <Foundation/Foundation.h>
#import <Flutter/Flutter.h>
#import <IronSource/IronSource.h>
#import "LevelPlayNativeAdViewFactory.h"
/**
 * 类是如何实现自定义原生广告的示例。
 * 类必须接收 BinaryMessenger 和
 * 开发者要加载的原生广告布局。它还
 * 必须扩展 LevelPlayNativeAdViewFactory 并覆盖
 * 方法 bindNativeAdToView 以便使用 填充视图
 * 加载的原生广告。
 */
@interface NativeAdViewFactoryExample：LevelPlayNativeAdViewFactory <LevelPlayNativeAdViewFactoryDelegate>
- (instancetype)initWithMessenger:(id<FlutterBinaryMessenger>)levelPlayBinaryMessenger layoutName:(nullable NSString *)layoutName;
@end
/// m file
#import "NativeAdViewFactoryExample.h"
@implementation NativeAdViewFactoryExample
- (instancetype)initWithMessenger:(id<FlutterBinaryMessenger>)levelPlayBinaryMessenger layoutName:(nullable NSString *)layoutName {
    self = [super initWithMessenger:levelPlayBinaryMessenger delegate:self layoutName:layoutName];
    return self;
}
- (void)bindNativeAdToView:(LevelPlayNativeAd *)nativeAd isNativeAdView:(ISNativeAdView *)isNativeAdView {
    // Extract views
    UILabel *titleView = isNativeAdView.adTitleView;
    UILabel *bodyView = isNativeAdView.adBodyView;
    UILabel *advertiserView = isNativeAdView.adBodyView;
    UIButton *callToActionView = isNativeAdView.adCallToActionView;
    UIImageView *iconView = isNativeAdView.adAppIcon;
    LevelPlayMediaView *mediaView = isNativeAdView.adMediaView;
    // Bind native ad to view
    if (nativeAd != nil) {
        if (nativeAd.title != nil) {
            titleView.text = nativeAd.title;
            [isNativeAdView setAdTitleView:titleView];
        }
        if (nativeAd.body != nil) {
            bodyView.text = nativeAd.body;
            [isNativeAdView setAdBodyView:bodyView];
        }
        if (nativeAd.advertiser != nil) {
            advertiserView.text = nativeAd.advertiser;
            [isNativeAdView setAdAdvertiserView:advertiserView];
        }
        if (nativeAd.callToAction != nil) {
            [callToActionView setTitle:nativeAd.callToAction forState:UIControlStateNormal];
            [isNativeAdView setAdCallToActionView:callToActionView];
        }
        if (nativeAd.icon != nil) {
            iconView.image = nativeAd.icon.image;
            [isNativeAdView setAdAppIcon:iconView];
        }
        if (mediaView != nil) {
            [isNativeAdView setAdMediaView:mediaView];
        }
        // Register native ad views with the provided native ad
        [isNativeAdView registerNativeAdViews:nativeAd];
    }
}
@end

```

### 注册 NativeAdViewFactory##register-your-nativeadviewfactory

在 MainActivity 或 AppDelegate 中注册 类。

> **Note:**
>
> 唯一视图类型字符串必须与在 Flutter 端的 LevelPlayNativeAdView 小部件中设置的 viewType 相对应。

#### Android##android

```kotlin
 // Android Implementation 
import com.ironSource.ironsource_mediation.IronSourceMediationPlugin
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
类 MainActivity：FlutterActivity() {
    覆盖 fun configureFlutterEngine(flutterEngine：FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        // Custom native ad view template must be registered here
        IronSourceMediationPlugin.registerNativeAdViewFactory(flutterEngine, [YOUR_UNIQUE_VIEW_TYPE], NativeAdViewFactoryExample(flutterEngine.dartExecutor.binaryMessenger, R.布局.my_custom_native_ad_view)) // 您的 xml id
    }
    覆盖 fun cleanUpFlutterEngine(flutterEngine：FlutterEngine) {
        super.cleanUpFlutterEngine(flutterEngine)
        // Custom native ad view template must be unregistered here
        IronSourceMediationPlugin.unregisterNativeAdViewFactory(flutterEngine, viewType)
    }
}

```

请参阅 [my\_custom\_native\_ad\_view\_template.xml](https://github.com/ironsource-mobile/Flutter-SDK/blob/master/example/android/app/src/main/res/layout/my_custom_native_ad_view.xml) 以查看 Android NativeAdView 布局的示例。

#### iOS##ios

```objc
 // iOS Implementation 
#import "AppDelegate.h"
#import "GeneratedPluginRegistrant.h"
#import "NativeAdViewFactoryExample.h"
#import "IronSourceMediationPlugin.h"
@implementation AppDelegate
- (BOOL) 应用程序：(UIApplication *) 应用程序
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];
  UIViewController *rootViewController = self.window.rootViewController;
  // Check if the root view controller is a FlutterViewController
  if ([rootViewController isKindOfClass:[FlutterViewController class]]) {
    // Cast the root view controller to FlutterViewController
    FlutterViewController *flutterViewController = (FlutterViewController *)rootViewController;
    NativeAdViewFactoryExample *nativeAdViewFactoryExample = [[NativeAdViewFactoryExample alloc] initWithMessenger: flutterViewController.binaryMessenger layoutName: @"MyCustomNativeAdViewTemplate"]; // 您的 xib 名称
    // Custom native ad view template must be registered here
    [IronSourceMediationPlugin registerNativeAdViewFactory:self
                                                  viewTypeId:[YOUR_UNIQUE_VIEW_TYPE]
                                         nativeAdViewFactory:nativeAdViewFactoryExample];
  }
  // Override point for customization after application launch.
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end

```

有关 iOS NativeAdView 布局的示例，请参阅 [MyCustomNativeAdViewTemplate.xib](https://github.com/ironsource-mobile/Flutter-SDK/blob/master/example/ios/Runner/MyCustomNativeAdViewTemplate.xib)。

### 创建 LevelPlayNativeAdView##create-levelplaynativeadview

创建一个 LevelPlayNativeAdView 小部件来定义将托管加载的原生广告的容器。此对象将通过确定宽度和高度或设置容器的框约束来定义原生广告边界。它还可以处理原生广告元素样式，例如：作品/游戏作品、正文、广告主和行动号召按钮。

> **Note:**
>
> 创建自定义模板时，请确保 viewType 与原生 Android 或 iOS 部分中指定的唯一视图类型对齐。

```dart
LevelPlayNativeAdView(
          height：[HEIGHT]，// 建议的高度
          width：[WIDTH]，// 建议的宽度
          nativeAd: _nativeAd,
          onPlatformViewCreated: () {
            _nativeAd?.loadAd(); // Recommeneded place to loadAd
          },
          viewType: [YOUR_UNIQUE_VIEW_TYPE]
)

```

### 加载广告##load-the-ad

调用 loadAd 加载原生广告。可以在原生广告视图容器的 onPlatformViewCreated 回调上或在开发者决定的另一个时间调用此方法。

```dart
_nativeAd?.loadAd();

```

### 销毁原生广告##destroy-the-native-ad

要销毁原生广告，请调用 destroyAd 方法：

```dart
_nativeAd?.destroyAd();

```

无法再加载已销毁的原生广告。如果要再次投放广告，必须重新创建广告容器小部件。

## LevelPlay Mediation 演示应用程序##levelplay-mediation-demo-app

Integration Demo app 演示如何在 app 中集成原生广告单元 API。

[下载 Flutter Demo 应用程序](https://github.com/ironsource-mobile/Flutter-SDK/tree/master/example)

验证与 [Integration Test Suite](/grow/levelplay/sdk/flutter/integration-test-suite/.md) 的集成。

## 后续步骤##next-steps

按照集成指南集成其他插页式广告网络或配置其他广告格式：

* [添加聚合网络](/grow/levelplay/sdk/flutter/mediation-networks.md)
* [奖励广告服务](/grow/levelplay/sdk/flutter/rewarded-ads-integration.md)
* [插页式广告服务](/grow/levelplay/sdk/flutter/interstitial-integration.md)
* [横幅广告服务](/grow/levelplay/sdk/flutter/banner-integration.md)
