> ## Documentation Index
> Fetch the complete documentation index at: https://docs.adrop.io/llms.txt
> Use this file to discover all available pages before exploring further.

# インタースティシャル広告

> Flutterアプリでインタースティシャル広告を実装する方法をご案内します。

## 概要

インタースティシャル広告は画面全体を覆うフルスクリーン広告です。自然な遷移ポイント（例：ゲームレベル完了、ページ遷移など）に表示すると効果的です。

### 主な機能

* 画面全体を覆うフルスクリーン広告
* 画像および動画広告をサポート
* フルスクリーンイベントコールバックを提供
* ロードと表示を分離して柔軟なタイミング制御

<Note>
  開発環境ではテストユニットIDを使用してください: `PUBLIC_TEST_UNIT_ID_INTERSTITIAL`
</Note>

***

## AdropInterstitialAd

### コンストラクタ

```dart theme={null}
AdropInterstitialAd({
  required String unitId,
  AdropInterstitialListener? listener,
})
```

**パラメータ**

| パラメータ      | タイプ                         | 必須 | 説明                         |
| ---------- | --------------------------- | -- | -------------------------- |
| `unitId`   | `String`                    | Y  | Ad Controlコンソールで作成したユニットID |
| `listener` | `AdropInterstitialListener` | N  | 広告イベントリスナー                 |

### プロパティ

| プロパティ            | タイプ              | 説明                 |
| ---------------- | ---------------- | ------------------ |
| `isLoaded`       | `bool`           | 広告のロード完了状態         |
| `unitId`         | `String`         | 広告ユニットID           |
| `creativeId`     | `String`         | クリエイティブID          |
| `txId`           | `String`         | トランザクションID         |
| `campaignId`     | `String`         | キャンペーンID           |
| `destinationURL` | `String`         | 遷移先URL             |
| `browserTarget`  | `BrowserTarget?` | ブラウザターゲット（外部または内部） |

### メソッド

| メソッド        | 戻り値の型          | 説明                                             |
| ----------- | -------------- | ---------------------------------------------- |
| `load()`    | `Future<void>` | 広告をロードします                                      |
| `show()`    | `Future<void>` | 広告を画面に表示します                                    |
| `close()`   | `Future<void>` | インタースティシャル広告をプログラム的に閉じます（Android専用、iOSではno-op） |
| `dispose()` | `Future<void>` | リソースを解放します                                     |

<Note>
  `close()`を呼び出すと広告が閉じられ、`onAdDidDismissFullScreen`コールバックが続いて呼び出されます。`onAdBackButtonPressed`コールバックで`close()`を呼び出さない場合、広告は閉じられずコールバックのみが受信されます。閉じるかどうかは開発者が決定します。
</Note>

***

## 基本的な使用方法

```dart theme={null}
import 'package:flutter/material.dart';
import 'package:adrop_ads_flutter/adrop_ads_flutter.dart';

class InterstitialExample extends StatefulWidget {
  const InterstitialExample({super.key});

  @override
  State<InterstitialExample> createState() => _InterstitialExampleState();
}

class _InterstitialExampleState extends State<InterstitialExample> {
  bool isLoaded = false;
  AdropInterstitialAd? interstitialAd;

  @override
  void initState() {
    super.initState();
    _createInterstitialAd();
  }

  void _createInterstitialAd() {
    interstitialAd = AdropInterstitialAd(
      unitId: 'YOUR_UNIT_ID',
      listener: AdropInterstitialListener(
        onAdReceived: (ad) {
          debugPrint('インタースティシャル広告ロード成功: ${ad.creativeId}');
          setState(() {
            isLoaded = true;
          });
        },
        onAdFailedToReceive: (ad, errorCode) {
          debugPrint('インタースティシャル広告ロード失敗: $errorCode');
        },
        onAdClicked: (ad) {
          debugPrint('インタースティシャル広告クリック');
        },
        onAdDidPresentFullScreen: (ad) {
          debugPrint('インタースティシャル広告表示');
        },
        onAdDidDismissFullScreen: (ad) {
          debugPrint('インタースティシャル広告閉じる');
        },
        onAdFailedToShowFullScreen: (ad, errorCode) {
          debugPrint('インタースティシャル広告表示失敗: $errorCode');
        },
        onAdBackButtonPressed: (ad) {
          debugPrint('戻るボタン押下');
        },
      ),
    );
  }

  void loadAd() {
    interstitialAd?.load();
  }

  void showAd() {
    if (isLoaded) {
      interstitialAd?.show();
    }
  }

  @override
  void dispose() {
    interstitialAd?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('インタースティシャル広告サンプル')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: loadAd,
              child: const Text('広告をロード'),
            ),
            const SizedBox(height: 16),
            ElevatedButton(
              onPressed: isLoaded ? showAd : null,
              child: const Text('広告を表示'),
            ),
          ],
        ),
      ),
    );
  }
}
```

***

## AdropInterstitialListener

インタースティシャル広告イベントを処理するリスナーです。

### コールバック関数

```dart theme={null}
AdropInterstitialListener(
  onAdReceived: (AdropAd ad) {
    // 広告ロード成功
  },
  onAdClicked: (AdropAd ad) {
    // 広告クリック
  },
  onAdImpression: (AdropAd ad) {
    // 広告表示
  },
  onAdWillPresentFullScreen: (AdropAd ad) {
    // 広告表示直前（iOS専用）
  },
  onAdDidPresentFullScreen: (AdropAd ad) {
    // 広告が表示された
  },
  onAdWillDismissFullScreen: (AdropAd ad) {
    // 広告が閉じる直前（iOS専用）
  },
  onAdDidDismissFullScreen: (AdropAd ad) {
    // 広告が閉じた
  },
  onAdFailedToReceive: (AdropAd ad, AdropErrorCode errorCode) {
    // 広告ロード失敗
  },
  onAdFailedToShowFullScreen: (AdropAd ad, AdropErrorCode errorCode) {
    // 広告表示失敗
  },
  onAdBackButtonPressed: (AdropAd ad) {
    // 戻るボタン押下（Android専用）
  },
)
```

### コールバックの説明

| コールバック                       | 説明                                  |
| ---------------------------- | ----------------------------------- |
| `onAdReceived`               | 広告ロード成功時に呼び出される                     |
| `onAdClicked`                | 広告クリック時に呼び出される                      |
| `onAdImpression`             | 広告表示時に呼び出される                        |
| `onAdWillPresentFullScreen`  | 広告表示直前に呼び出される（iOS専用）                |
| `onAdDidPresentFullScreen`   | 広告表示後に呼び出される                        |
| `onAdWillDismissFullScreen`  | 広告が閉じる直前に呼び出される（iOS専用）              |
| `onAdDidDismissFullScreen`   | 広告が閉じた後に呼び出される                      |
| `onAdFailedToReceive`        | 広告ロード失敗時に呼び出される                     |
| `onAdFailedToShowFullScreen` | 広告表示失敗時に呼び出される                      |
| `onAdBackButtonPressed`      | 広告表示中に戻るボタンが押された時に呼び出される（Android専用） |

***

## 広告のライフサイクル

```mermaid theme={null}
graph TD
    A[生成] --> B[loadを呼び出す]
    B --> C{ロード結果}
    C -->|成功| D[onAdReceived]
    C -->|失敗| E[onAdFailedToReceive]
    D --> F[showを呼び出す]
    F --> G{表示結果}
    G -->|成功| H[onAdWillPresentFullScreen]
    G -->|失敗| I[onAdFailedToShowFullScreen]
    H --> J[onAdDidPresentFullScreen]
    J --> K[ユーザーインタラクション]
    K -->|クリック| L[onAdClicked]
    K -->|閉じる| M[onAdWillDismissFullScreen]
    K -->|戻るボタン Android| P[onAdBackButtonPressed]
    P -->|close呼び出し| M
    M --> N[onAdDidDismissFullScreen]
    N --> O[disposeまたは再生成]
```

***

## 広告の再生成

インタースティシャル広告は1回限りです。一度表示された広告は再度表示できないため、新しい広告をロードするにはインスタンスを再生成する必要があります。

```dart theme={null}
class _InterstitialState extends State<InterstitialWidget> {
  bool isLoaded = false;
  bool isShown = false;
  AdropInterstitialAd? interstitialAd;

  @override
  void initState() {
    super.initState();
    _createInterstitialAd();
  }

  void _createInterstitialAd() {
    interstitialAd?.dispose();
    interstitialAd = AdropInterstitialAd(
      unitId: 'YOUR_UNIT_ID',
      listener: AdropInterstitialListener(
        onAdReceived: (ad) {
          setState(() {
            isLoaded = true;
          });
        },
        onAdDidPresentFullScreen: (ad) {
          setState(() {
            isShown = true;
          });
        },
        onAdDidDismissFullScreen: (ad) {
          // 広告が閉じた後に新しい広告を準備
          _createInterstitialAd();
          interstitialAd?.load();
        },
      ),
    );

    setState(() {
      isLoaded = false;
      isShown = false;
    });
  }

  @override
  void dispose() {
    interstitialAd?.dispose();
    super.dispose();
  }
}
```

***

## エラー処理

```dart theme={null}
class _InterstitialState extends State<InterstitialWidget> {
  bool isLoaded = false;
  AdropErrorCode? errorCode;
  AdropInterstitialAd? interstitialAd;

  void _createInterstitialAd() {
    interstitialAd = AdropInterstitialAd(
      unitId: 'YOUR_UNIT_ID',
      listener: AdropInterstitialListener(
        onAdReceived: (ad) {
          setState(() {
            isLoaded = true;
            errorCode = null;
          });
        },
        onAdFailedToReceive: (ad, error) {
          setState(() {
            isLoaded = false;
            errorCode = error;
          });
          _handleError(error);
        },
        onAdFailedToShowFullScreen: (ad, error) {
          setState(() {
            errorCode = error;
          });
          _handleError(error);
        },
      ),
    );
  }

  void _handleError(AdropErrorCode error) {
    switch (error) {
      case AdropErrorCode.network:
        debugPrint('ネットワークエラーが発生しました。');
        break;
      case AdropErrorCode.adNoFill:
        debugPrint('表示する広告がありません。');
        break;
      case AdropErrorCode.adShown:
        debugPrint('すでに表示された広告です。');
        break;
      default:
        debugPrint('エラーが発生しました: ${error.code}');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: interstitialAd?.load,
          child: const Text('広告をロード'),
        ),
        ElevatedButton(
          onPressed: isLoaded ? interstitialAd?.show : null,
          child: const Text('広告を表示'),
        ),
        if (errorCode != null)
          Text(
            'エラー: ${errorCode?.code}',
            style: const TextStyle(color: Colors.red),
          ),
      ],
    );
  }
}
```

***

## ベストプラクティス

### 1. 適切なタイミングで表示

インタースティシャル広告は自然な遷移ポイントで表示してください。

```dart theme={null}
// 良い例：レベル完了後
void onLevelComplete() {
  showInterstitialAd();
  navigateToNextLevel();
}

// 悪い例：アプリ起動直後
void onAppStart() {
  showInterstitialAd(); // ユーザー体験を低下させる
}
```

### 2. 事前にロード

広告を事前にロードしておくと、表示時に遅延なく表示できます。

```dart theme={null}
class GameScreen extends StatefulWidget {
  @override
  State<GameScreen> createState() => _GameScreenState();
}

class _GameScreenState extends State<GameScreen> {
  AdropInterstitialAd? interstitialAd;
  bool isAdReady = false;

  @override
  void initState() {
    super.initState();
    _preloadAd();
  }

  void _preloadAd() {
    interstitialAd = AdropInterstitialAd(
      unitId: 'YOUR_UNIT_ID',
      listener: AdropInterstitialListener(
        onAdReceived: (ad) {
          setState(() {
            isAdReady = true;
          });
        },
        onAdDidDismissFullScreen: (ad) {
          // 次の広告を事前にロード
          _preloadAd();
        },
      ),
    );
    interstitialAd?.load();
  }

  void showAdIfReady() {
    if (isAdReady) {
      interstitialAd?.show();
      setState(() {
        isAdReady = false;
      });
    }
  }

  @override
  void dispose() {
    interstitialAd?.dispose();
    super.dispose();
  }
}
```

### 3. 頻度制限

ユーザー体験のために広告表示頻度を制限してください。

```dart theme={null}
class AdManager {
  static int _interstitialCount = 0;
  static const int _maxInterstitialsPerSession = 3;
  static DateTime? _lastInterstitialTime;
  static const Duration _minInterval = Duration(minutes: 2);

  static bool canShowInterstitial() {
    if (_interstitialCount >= _maxInterstitialsPerSession) {
      return false;
    }

    if (_lastInterstitialTime != null) {
      final elapsed = DateTime.now().difference(_lastInterstitialTime!);
      if (elapsed < _minInterval) {
        return false;
      }
    }

    return true;
  }

  static void onInterstitialShown() {
    _interstitialCount++;
    _lastInterstitialTime = DateTime.now();
  }
}
```

### 4. リソース管理

使用していない広告インスタンスは必ず解放してください。

```dart theme={null}
@override
void dispose() {
  interstitialAd?.dispose();
  super.dispose();
}
```

***

## 完全なサンプル

```dart theme={null}
import 'package:flutter/material.dart';
import 'package:adrop_ads_flutter/adrop_ads_flutter.dart';

class InterstitialAdPage extends StatefulWidget {
  const InterstitialAdPage({super.key});

  @override
  State<InterstitialAdPage> createState() => _InterstitialAdPageState();
}

class _InterstitialAdPageState extends State<InterstitialAdPage> {
  bool isLoaded = false;
  bool isLoading = false;
  bool isShown = false;
  AdropErrorCode? errorCode;
  AdropInterstitialAd? interstitialAd;

  @override
  void initState() {
    super.initState();
    _createInterstitialAd();
  }

  void _createInterstitialAd() {
    interstitialAd?.dispose();
    interstitialAd = AdropInterstitialAd(
      unitId: 'PUBLIC_TEST_UNIT_ID_INTERSTITIAL', // テストユニットID
      listener: AdropInterstitialListener(
        onAdReceived: (ad) {
          debugPrint('広告ロード成功');
          debugPrint('クリエイティブID: ${ad.creativeId}');
          debugPrint('キャンペーンID: ${ad.campaignId}');
          setState(() {
            isLoaded = true;
            isLoading = false;
            errorCode = null;
          });
        },
        onAdClicked: (ad) {
          debugPrint('広告クリック: ${ad.destinationURL}');
        },
        onAdImpression: (ad) {
          debugPrint('広告表示: ${ad.creativeId}');
        },
        onAdWillPresentFullScreen: (ad) {
          debugPrint('広告表示予定');
        },
        onAdDidPresentFullScreen: (ad) {
          debugPrint('広告が表示された');
          setState(() {
            isShown = true;
          });
        },
        onAdWillDismissFullScreen: (ad) {
          debugPrint('広告が閉じる予定');
        },
        onAdDidDismissFullScreen: (ad) {
          debugPrint('広告が閉じた');
          // 新しい広告を準備
          _createInterstitialAd();
        },
        onAdFailedToReceive: (ad, error) {
          debugPrint('広告ロード失敗: $error');
          setState(() {
            isLoaded = false;
            isLoading = false;
            errorCode = error;
          });
        },
        onAdFailedToShowFullScreen: (ad, error) {
          debugPrint('広告表示失敗: $error');
          setState(() {
            errorCode = error;
          });
        },
        onAdBackButtonPressed: (ad) {
          debugPrint('戻るボタン押下');
        },
      ),
    );

    setState(() {
      isLoaded = false;
      isShown = false;
      errorCode = null;
    });
  }

  void loadAd() {
    setState(() {
      isLoading = true;
      errorCode = null;
    });
    interstitialAd?.load();
  }

  void showAd() {
    if (isLoaded) {
      interstitialAd?.show();
    }
  }

  @override
  void dispose() {
    interstitialAd?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('インタースティシャル広告サンプル'),
      ),
      body: SafeArea(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              // ロードボタン
              ElevatedButton(
                onPressed: isLoading ? null : loadAd,
                child: Text(isLoading ? 'ロード中...' : '広告をロード'),
              ),
              const SizedBox(height: 16),

              // 表示ボタン
              ElevatedButton(
                onPressed: isLoaded ? showAd : null,
                child: const Text('広告を表示'),
              ),
              const SizedBox(height: 16),

              // リセットボタン
              TextButton(
                onPressed: (isShown || errorCode != null)
                    ? () => _createInterstitialAd()
                    : null,
                child: const Text('リセット'),
              ),
              const SizedBox(height: 24),

              // ステータス表示
              Text('ロード済み: ${isLoaded ? "はい" : "いいえ"}'),
              Text('表示済み: ${isShown ? "はい" : "いいえ"}'),

              // エラー表示
              if (errorCode != null) ...[
                const SizedBox(height: 16),
                Text(
                  'エラー: ${errorCode?.code}',
                  style: const TextStyle(color: Colors.red),
                ),
              ],
            ],
          ),
        ),
      ),
    );
  }
}
```

***

## バックフィル広告

バックフィル広告が有効な場合、ダイレクト広告がない時に自動的にバックフィル広告がロードされます。エラーコードを使ってバックフィル関連の状態を処理できます。

```dart theme={null}
interstitialAd = AdropInterstitialAd(
  unitId: 'YOUR_UNIT_ID',
  listener: AdropInterstitialListener(
    onAdReceived: (ad) {
      debugPrint('広告ロード完了: ${ad.creativeId}');
    },
    onAdFailedToReceive: (ad, errorCode) {
      switch (errorCode) {
        case AdropErrorCode.adNoFill:
          debugPrint('ダイレクト広告なし');
          break;
        case AdropErrorCode.backfillNoFill:
          debugPrint('バックフィル広告もありません');
          break;
        default:
          debugPrint('広告ロード失敗: ${errorCode.code}');
      }
    },
  ),
);
```

<Note>
  バックフィル広告を使用するには、ネイティブプラットフォームにバックフィル依存性を追加する必要があります。[はじめに](/ja/sdk/flutter/overview)を参照してください。
</Note>

***

## 次のステップ

<CardGroup cols={2}>
  <Card title="リワード広告" href="/ja/sdk/flutter/rewarded">
    報酬を提供するリワード広告を実装する
  </Card>

  <Card title="ポップアップ広告" href="/ja/sdk/flutter/popup">
    ポップアップ形式で表示される広告を実装する
  </Card>

  <Card title="リファレンス" href="/ja/sdk/flutter/reference">
    タイプ、メソッド、エラーコードを参照する
  </Card>
</CardGroup>
