# Flutter 的奖励广告服务集成

> 将奖励视频广告服务集成到 Flutter 应用程序中，利用广告位、封顶、节奏和手动加载选项来优化用户参与度。

> **Note:**
>
> 本文档与 SDK 8.6.0+ 相关。

## 先决条件##prerequisites

* 确保将 Flutter 插件[集成](/grow/levelplay/sdk/flutter/plugin-integration.md)到 app 中。
* 确保使用 LevelPlay Initialization API 初始化 SDK。
* 在 LevelPlay 后台中找到 AdUnitID。

## 创建奖励并注册到事件##create-rewarded-and-register-to-events

收到`onInitSuccess`回调后，您可以使用 LevelPlay 平台中定义的相关 Ad Unit ID 创建广告单元（初始化 LevelPlay SDK 步骤）。

为创建的奖励广告单元设置奖励监听器，以便了解广告投放情况。

```dart
final LevelPlayRewardedAd _rewardedAd = LevelPlayRewardedAd(adUnitId: [YOUR_AD_UNIT_ID]);
@override
void initState() {
    super.initState();
    _rewardedAd.setListener(this);
}
// LevelPlayRewardedAdListener methods
@override
void onAdLoaded(LevelPlayAdInfo adInfo) {}
@override
void onAdLoadFailed(LevelPlayAdError error) {} 
@override
void onAdDisplayed(LevelPlayAdInfo adInfo) {}
@override
void onAdDisplayFailed(LevelPlayAdError error,
 LevelPlayAdInfo adInfo) {
@override 
void onAdClosed(LevelPlayAdInfo adInfo) {}
@override
void onAdClicked(LevelPlayAdInfo adInfo) {} 
@override
void onAdInfoChanged(LevelPlayAdInfo adInfo) {}
@override
void onAdRewarded(LevelPlayReward reward, LevelPlayAdInfo adInfo) {}
```

### LevelPlay 奖励广告回调##levelplay-rewarded-ad-callbacks

* `onAdLoaded`：成功加载广告时提供
* `onAdLoadFailed`：在广告加载失败时提供。包含广告单元信息
* `onAdDisplayed`：在显示广告时提供。这相当于展示
* `onAdDisplayFailed`（可选）：广告无法显示时提供
* `onAdRewarded`：在广告获得奖励时提供。其中包含广告单元信息和奖励信息。
* `onAdClicked`（可选）：在用户点击广告时提供
* `onAdClosed`：广告关闭时提供
* `onAdInfoChanged`（可选）：在更新广告信息时提供。加载另一个广告后可用，并且包含更高的 CPM/速率

## 获取奖励广告详细信息##get-rewarded-ad-details

使用 getReward API 可以访问您在 LevelPlay 后台中设置的奖励数据。与其他聚合 API 不同，这是一个独立调用，在初始化后返回存储在 SDK 本地的数据。这使您能够构建动态、数据驱动的 UI，在用户参与广告之前告知他们潜在的奖励，从而无需在app中硬编码奖励值。

### 先决条件##prerequisites

在实现 getReward API 之前，请确保项目满足以下技术要求：

* SDK 初始化：调用 initSDK 并等待 onInitializationSuccess 回调以确保奖励数据已缓存。
* Ad Object 实例：在调用 API 之前，使用有效的 Ad Unit ID 实例化奖励广告对象。
* 最低 SDK 版本：使用 LevelPlay SDK 8.1.0 或更高版本（原生或 Unity 软件包）。

### 最佳实践##best-practices

遵循这些建议可确保稳定且可预测的集成。

* **初始化成功时调用**：调用 getReward 的最佳时间是初始化成功监听器器内部。这样可以确保 UI 在用户进入屏幕时就绪。
* **检查空状态**：在更新 UI 之前，请始终验证该数量> 0。如果在初始化期间发生网络报错，这将确保平滑的用户体验。
* **放置/位置精度**：确保在 getReward("placementName") 中使用的字符串与 LevelPlay 后台中定义的名称完全匹配。

### API 结构##api-structure

getReward 方法允许您从 LevelPlay 后台访问同步的奖励数据。使用此方法可以查询本地 SDK 缓存中指定的广告放置/位置或全局广告单元默认值。

#### getReward##getreward

获取指定的广告放置/位置或默认广告单元的奖励名称和金额。没有其他参数可以使用。

* `placementName`：在 LevelPlay 后台中定义的放置/位置的唯一标识符。通道`null`，用于获取广告单元的默认奖励。

返回一个 LevelPlayReward 对象，其中包含名称（字符串）和金额（int）。

### 初始设置##initial-setup

getReward API 充当 LevelPlay SDK 的核心组件，在如下逻辑下运行以确保数据无延迟可用：

* 集成功能：由于奖励数据是在初始 SDK 设置期间获取的，因此 API 调用是即时的，不需要网络请求。
* 编辑器配置：将 app 与 LevelPlay SDK 集成后，API 可以立即使用。测试此功能不需要额外的资源或插件。

### 了解奖励选择逻辑##understand-reward-selection-logic

API 根据指定的层级视图返回 LevelPlayReward 对象。了解此逻辑有助于排除出现指定的奖励的原因。

* 放置/位置级别：如果在调用中提供了有效的广告放置/位置称，SDK 将返回控制面板中为该广告位放置/位置的指定的奖励。
* 广告单元级别：如果广告放置/位置名称为 null 或未找到，SDK 将回退到为广告单元定义的默认奖励。
* 回退状态：如果在初始化完成之前调用 API，则返回一个字符串名称为空且值为 0 的奖励对象。

### 动态更新 UI##update-your-ui-dynamically

使用 getReward API 可将静态按钮变换为高意图的行动调用。例如：您可以显示“Watch to earn 50 Gold”，而不是通用的“Watch Video”按钮。

* 验证金额：在更新 UI 组件之前，请务必验证 reward.amount > 0。
* 事件驱动的更新：在初始化成功监听器器中调用 API 以确保 UI 在用户进入屏幕时准确无误。
* 区分大小写：确保代码中的放置/位置名称字符串与 LevelPlay 后台完全匹配；不匹配的字符串将触发器广告单元回退。

### getReward API 实现故障排除##troubleshooting-getreward-api-implementation

* 奖励金额返回 0：如果在 onInitializationSuccess 回调之前调用 API，通常会发生这种情况。在查询奖励之前，请确保 SDK 完全准备就绪。
* 显示的错误奖励类型：检查是否有多个广告位。如果放置/位置名称拼写错误，SDK 默认认为主广告单元奖励，而不是指定的广告放置/位置奖励。

## 加载奖励广告##load-rewarded-ad

收到 **onInitSuccess** 回调后，即可加载奖励广告。应使用 方法执行此操作：

```dart
_rewardedAd.loadAd();
```

## 显示奖励广告##show-rewarded-ad

您可以在收到 **onAdLoaded** 回调后使用 showAd API 展示奖励广告。

如果使用[广告位](/grow/levelplay/platform/settings/placements.md)，请将广告位名称作为 API 的一部分共享，如下所示。

```dart
// Show ad without placement
_rewardedAd.showAd();
// Show ad with placement
_rewardedAd.showAd(placement: [YOUR_PLACEMENT]);
```

## 检查广告就绪状态##check-ad-ready

为了避免显示失败，并确保广告可以正确显示，建议在调用 showAd() API 之前使用以下 API。

* `isAdReady`：如果广告加载成功并且广告单元未设置上限，则返回 true，否则返回 false。
* `isPlacementCapped`：限制有效放置/位置时返回 true。如果放置/位置无效或未设置上限，此 API 将返回 false。

```dart
// Check that ad is ready and that the placement is not capped 
if(_rewardedAd.isAdReady() && !LevelPlayRewardedAd.isPlacementCapped([YOUR_PLACEMENT])) {
     _rewardedAd.showAd(placement:[YOUR_PLACEMENT]);
}
```

广告成功展示给玩家后，您可以加载另一个广告，重复加载奖励广告步骤。一时间加载单个广告时，无需创建新的广告实体。

### 动态 UserId##dynamic-userid

动态 UserID 是一个参数，用于验证可在整个会话中更改的 AdRewarded 交易。您将通过[服务器到服务器](/grow/levelplay/platform/settings/server-to-server-callback.md)的广告奖励回调收到此参数，必须在调用 showAd 之前设置此参数。

* 字符字符串必须为 1 到 64 个字母数字角色。
* 您将在回调网址中收到一个 `dynamicUserId` 参数以及奖励详细信息。

```dart
LevelPlay.setDynamicUserId("userId");
```

## 奖励用户##reward-the-user

LevelPlay SDK 将在用户每次成功完成视频时触发`onAdRewarded`。

`onAdRewarded` 和 `onAdClosed` 是异步的。确保设置监听器以授予奖励，即使在`onAdClosed`后解雇`onAdRewarded`的情况下也是如此。

```dart
@override
void onAdRewarded(LevelPlayReward reward, LevelPlayAdInfo adInfo) {
    // Implement logic to grant the reward to the user
}
```

## 多个广告单元奖励 API##multiple-ad-unit-rewarded-apis

| Category | 旧版                               | Ad Unit（广告单元）（新）      |
| -------- | -------------------------------- | --------------------- |
| 类        | `IronSource`                     | `LevelPlayRewardedAd` |
| API      | `loadRewardedVideo`              | `loadAd`              |
| API      | `showRewardedVideo`              | `showAd`              |
| API      | `isRewardedVideoPlacementCapped` | `isPlacementCapped`   |
| API      | `isRewardedVideoAvailable`       | `isAdReady`           |
| API      | `placement.getRewardName`        | `reward.name`         |
| API      | `placement.getRewardAmount`      | `reward.amount`       |

## 奖励广告的完整实现示例##full-implementation-example-of-rewarded-ad

```dart
final LevelPlayRewardedAd _rewardedAd = LevelPlayRewardedAd(adUnitId:'YOUR_AD_UNIT_ID');
@override
void initState() {
    super.initState();
    _rewardedAd.setListener(this);
    _rewardedAd.loadAd();
}
@override
void onAdRewarded(LevelPlayReward reward, LevelPlayAdInfo adInfo) {
    // Implement your logic here...
}
@override
void onAdClicked(LevelPlayAdInfo adInfo) {
    // Implement your logic here...
}
@override
void onAdClosed(LevelPlayAdInfo adInfo) {
    // Implement your logic here...
}
@override
void onAdDisplayFailed(LevelPlayAdError error, LevelPlayAdInfo adInfo) {
    // Implement your logic here...
}
@override
void onAdDisplayed(LevelPlayAdInfo adInfo) {
    // Implement your logic here...
}
@override
void onAdInfoChanged(LevelPlayAdInfo adInfo) {
    // Implement your logic here...
}
@override
void onAdLoadFailed(LevelPlayAdError error) {
    // Implement your logic here...
}
@override
void onAdLoaded(LevelPlayAdInfo adInfo) {
    // Implement your logic here, for example showing the ad
    _rewardedAd.showAd();
}
// Rest of the widget
// End of widget...
```
