# React Native 的原生广告服务集成

> 将原生广告服务集成到 React Native 应用程序中，使用预定义或自定义模板提供可自定义的广告体验。

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

## 先决条件##prerequisites

确保已将 LevelPlay React 原生插件 8.4.0+ 正确集成到应用程序中。[此处](/grow/levelplay/sdk/react/plugin-integration.md)概述了集成。

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

有两种方法可以使用 React Native 插件集成 LevelPlay 原生广告服务：

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

## 原生模板##native-templates

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

有两个模板选项：

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

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

要集成原生模板，请按照以下步骤操作：

### 步骤 1.创建 LevelPlayNativeAd 对象##step-1.-create-levelplaynativead-object

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

```js
import {
  LevelPlayNativeAd,
  type LevelPlayNativeAdListener、
  type LevelPlayAdInfo、
  type LevelPlayAdError、
} 来自“Unity LevelPlay-mediation”

nativeAd = LevelPlayNativeAd.builder()
  .withPlacement('YOUR_PLACEMENT')
  .withListener(listener)
  .build();
```

### 步骤 2.实现监听器##step-2.-implement-the-listener

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

```js
const 监听器：LevelPlayNativeAdListener = {
  /** 在点击原生广告后调用。*/
  onAdClicked：（nativeAd：LevelPlayNativeAd、adInfo：LevelPlayAdInfo) => {,
  /** 在录制原生广告展示后调用。*/
  onAdImpression：（nativeAd：LevelPlayNativeAd、adInfo：LevelPlayAdInfo) => {,
  /** 在原生广告尝试加载但失败后调用。*/
  onAdLoadFailed：（nativeAd：LevelPlayNativeAd，报错：LevelPlayAdError) => {}，
  /** 在成功加载原生广告后调用。*/
  onAdLoaded：（nativeAd：LevelPlayNativeAd、adInfo：LevelPlayAdInfo) => {,
};
```

### 步骤 3.创建 LevelPlayNativeAdView##step-3.-create-levelplaynativeadview

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

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

```js
<LevelPlayNativeAdView
    style={{
       width：300,// Medium Type 的建议宽度
       height：350 // Medium Type 的建议高度
    }}
    nativeAd={nativeAd} 
    templateType={LevelPlayTemplateType.Medium}
    templateStyle={[[LevelPlayNativeAdTemplateStyle] optional]}
  />
<LevelPlayNativeAdView
    style={{
       width：300,// Small Type 的建议宽度
       height：175 // Small Type 的建议高度
    }}
    nativeAd={nativeAd} 
    templateType={LevelPlayTemplateType.Small}
    templateStyle={[[LevelPlayNativeAdTemplateStyle] optional]}
  />
```

### 步骤 3.加载广告##step-3.-load-the-ad

调用 loadAd 方法加载原生广告。可以在 useEffect 钩子或开发者决定的另一个时间调用它。

```js
nativeAd?.loadAd();
```

### 步骤 4.销毁原生广告##step-4.-destroy-the-native-ad

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

```js
nativeAd?.destroyAd();
```

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

## 自定义模板设置##custom-templates-setup

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

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

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

### 步骤 1.创建 NativeAdViewManager##step-1.-create-nativeadviewmanager

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

**Android**

```js
// Android Implementation
导入 Android.widget.按钮
导入 Android.widget.ImageView
import Android
import com.facebook.react.bridge.ReactApplicationContext
import com.ironsource.mediationsdk.ads.nativead.LevelPlayMediaView
import com.ironsource.mediationsdk.ads.nativead.LevelPlayNativeAd
import com.ironsource.mediationsdk.ads.nativead.NativeAdLayout
import com.ironsource.react_native_mediation.R
import com.ironsource.react_native_mediation.RCTLevelPlayNativeAdViewManager
class NativeAdViewManagerExample(
  reactApplicationContext:ReactApplicationContext,
  layoutId:Int
):RCTLevelPlayNativeAdViewManager(reactApplicationContext, 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：LevelPlayMediaView? = nativeAdLayout.findViewById(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)
    }
  }
  覆盖 fun getName()：字符串 {
    return "ExampleViewType"
  }
}
```

**iOS**

```js
// iOS Implementation 
/// h file
#import <Foundation/Foundation.h>
#import <LevelPlay/LevelPlay.h>
#import "RCTLevelPlayNativeAdViewManager.h"
@interface NativeAdViewManagerExample：RCTLevelPlayNativeAdViewManager <RCTLevelPlayNativeAdViewManagerDelegate>
@end
/// m file
#import "NativeAdViewManagerExample.h"
@implementation NativeAdViewManagerExample
RCT_EXPORT_MODULE(ExampleViewType) // View type definition
-（实例类型）init
{
  self = [super initWithDelegate:self layoutName:@"MyCustomNativeAdViewTemplate"];
  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
```

自定义视图类型字符串应与 React Native 端的 LevelPlayNativeAdView 组件中指定的 viewType 匹配。

* 对于 Android，应在覆盖的 getName 方法中返回视图类型字符串。应返回覆盖方法 getName 的视图类型字符串。
* 对于 iOS，应在 RCT\_EXPORT\_module\*\* 中指定视图类型字符串。\*\* 

### 步骤 2.为 Android 注册 NativeAdViewManager##step-2.-register-your-nativeadviewmanager-for-android

创建扩展 LevelPlayNativeAdViewManager 类的自定义原生广告类，请在 MainApplication 中注册 Android 类。

> **Note:**
>
> 自定义视图类型字符串必须与 React Native 端的 LevelPlayNativeAdView 组件中设置的 viewType 匹配。对于 iOS，由于模块导出用作注册，因此无需额外设置。

```js
 // Android Implementation
package com.ironsource.reactnativetester
导入 Android.app.Application
import com.facebook.react.PackageList
import com.facebook.react.ReactApplication
import com.facebook.react.ReactHost
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.soloader.SoLoader
import com.unity3d.reactnative.LevelPlayMediationPackage
类 MainApplication：Application(), ReactApplication {
  覆盖 val reactNativeHost：ReactNativeHost =
      对象：DefaultReactNativeHost(this) {
        覆盖 fun getPackages()：List<ReactPackage> =
            PackageList(this).packages.apply { }
              // Packages that cannot be autolinked yet can be added manually here, for example:
                add(CustomPackage())
            }
        覆盖 fun getJSMainModuleName()：字符串 = "index"
        覆盖 fun getUseDeveloperSupport()：Boolean = BuildConfig.DEBUG
        覆盖 val isNewArchEnabled：Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
        覆盖 val isHermesEnabled：Boolean = BuildConfig.IS_HERMES_ENABLED
      }
  覆盖 val reactHost：ReactHost
    get() = getDefaultReactHost(applicationContext, reactNativeHost)
  覆盖 fun onCreate() {
    super.onCreate()
    SoLoader.init(this, false)
    if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
      // If you opted-in for the New Architecture, we load the native entry point for this app.
      load()
    }
    // Register custom view managers
    LevelPlayMediationPackage.registerViewManager("ExampleViewType") { reactContext ->
        NativeAdViewManagerExample(reactContext, R.layout.my_custom_native_ad_view)
    }
  }
}
```

* 有关在 Android 上配置 NativeAdView 布局的示例，请参阅 [my\_custom\_native\_ad\_view\_template.xml](https://github.com/ironsource-mobile/react-native-SDK/blob/master/example/android/app/src/main/res/layout/my_custom_native_ad_view.xml)。
* 有关在 iOS 上配置 NativeAdView 布局的示例，请参阅 [GitHub](https://github.com/ironsource-mobile/react-native-SDK/tree/master/example/ios)。

### 步骤 3.创建 LevelPlayNativeAdView##step-3.-create-levelplaynativeadview

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

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

```js
<LevelPlayNativeAdView
    style={{
      width：300, // 原生广告容器的建议宽度
      height：350，// 建议高度（例如：中等样式布局）
    }}
    nativeAd={nativeAd}
    viewType="ExampleViewType"
    templateStyle={templateStyle} // optional:LevelPlayNativeAdTemplateStyle
  />
```

### 步骤 4.加载广告##step-4.-load-the-ad

调用 loadAd 方法加载原生广告。可根据 useEffect 或开发者决定的其他时间调用它。

```js
nativeAd?.loadAd();
```

### 步骤 5。销毁原生广告##step-5.-destroy-the-native-ad

要销毁原生广告，请调用原生广告对象的 destroyAd 方法。

```js
nativeAd?.destroyAd();
```

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