> ## 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.

# WebViewガイド

> FlutterのWebViewでバックフィル広告を表示する方法

## 概要

Flutterアプリで`Adrop.registerWebView`を使用して、WebView内にバックフィル広告を表示できます。

***

## 前提条件

プロジェクトに以下のパッケージを追加してください：

```bash theme={null}
flutter pub add webview_flutter webview_flutter_android webview_flutter_wkwebview
```

<Warning>
  WebViewバックフィル広告には、AndroidとiOSの両方で`adrop-ads-backfill`の設定が必要です。設定方法は[はじめに](/ja/sdk/flutter/overview)を参照してください。
</Warning>

***

## プラットフォーム設定

WebViewでバックフィル広告を有効にするには、ネイティブプラットフォームの設定が必要です。

<Tabs>
  <Tab title="Android">
    `android/app/src/main/AndroidManifest.xml`に以下を追加してください：

    ```xml AndroidManifest.xml theme={null}
    <manifest>
        <application>
            <!-- WebViewバックフィル広告連携 -->
            <meta-data
                android:name="com.google.android.gms.ads.INTEGRATION_MANAGER"
                android:value="webview"/>
        </application>
    </manifest>
    ```
  </Tab>

  <Tab title="iOS">
    `ios/Runner/Info.plist`に以下のキーを追加してください：

    ```xml Info.plist theme={null}
    <key>GADIntegrationManager</key>
    <string>webview</string>
    ```
  </Tab>
</Tabs>

<Warning>
  この設定はWebViewでバックフィル広告が正常に動作するために必要です。設定がないと、バックフィル広告が表示されない場合があります。
</Warning>

***

## WebViewの登録

`WebViewController`を作成し、プラットフォーム固有の識別子を取得して、コンテンツをロードする前に`Adrop.registerWebView`で登録してください。

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

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

  @override
  State<WebViewScreen> createState() => _WebViewScreenState();
}

class _WebViewScreenState extends State<WebViewScreen> {
  late final WebViewController _controller;
  bool _isReady = false;

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

    final PlatformWebViewControllerCreationParams params;
    if (WebViewPlatform.instance is WebKitWebViewPlatform) {
      params = WebKitWebViewControllerCreationParams(
        allowsInlineMediaPlayback: true,
        mediaTypesRequiringUserAction: const <PlaybackMediaTypes>{},
      );
    } else {
      params = const PlatformWebViewControllerCreationParams();
    }

    _controller = WebViewController.fromPlatformCreationParams(params)
      ..setJavaScriptMode(JavaScriptMode.unrestricted);

    _registerAndLoad();
  }

  Future<void> _registerAndLoad() async {
    final int identifier;
    if (Platform.isAndroid) {
      identifier =
          (_controller.platform as AndroidWebViewController).webViewIdentifier;
    } else if (Platform.isIOS) {
      identifier =
          (_controller.platform as WebKitWebViewController).webViewIdentifier;
    } else {
      return;
    }

    await Adrop.registerWebView(identifier);

    setState(() => _isReady = true);
    _controller.loadRequest(Uri.parse('https://your-website.com'));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _isReady
          ? WebViewWidget(controller: _controller)
          : const Center(child: CircularProgressIndicator()),
    );
  }
}
```

***

## WebView識別子の取得

`webViewIdentifier`はプラットフォームごとに異なる方法で取得します：

| プラットフォーム | コントローラー                    | プロパティ                |
| -------- | -------------------------- | -------------------- |
| Android  | `AndroidWebViewController` | `.webViewIdentifier` |
| iOS      | `WebKitWebViewController`  | `.webViewIdentifier` |

```dart theme={null}
if (Platform.isAndroid) {
  identifier =
      (_controller.platform as AndroidWebViewController).webViewIdentifier;
} else if (Platform.isIOS) {
  identifier =
      (_controller.platform as WebKitWebViewController).webViewIdentifier;
}
```

<Note>
  `Adrop.registerWebView()`はWebコンテンツをロードする前に呼び出してください。登録完了後にURLをロードする必要があります。
</Note>

***

## iOS WebView設定

iOSでは、`WebKitWebViewControllerCreationParams`を使用してインラインメディア再生を設定してください：

```dart theme={null}
final params = WebKitWebViewControllerCreationParams(
  allowsInlineMediaPlayback: true,
  mediaTypesRequiringUserAction: const <PlaybackMediaTypes>{},
);

_controller = WebViewController.fromPlatformCreationParams(params)
  ..setJavaScriptMode(JavaScriptMode.unrestricted);
```

<Warning>
  WebViewバックフィル広告には`adrop-ads-backfill`モジュールが必要です。モジュールがインストールされていない場合、`registerWebView()`は無視されます。
</Warning>

***

## 外部URLの処理

アプリで自社ドメイン以外のURLを外部ブラウザで開くロジックがある場合、広告リソースリクエスト（例：`googleads.g.doubleclick.net`）がブロックされないようにする必要があります。

広告リソース（iframe、スクリプトなど）は広告SDKによって自動的にロードされ、ユーザーが直接クリックしたものではありません。**メインフレームのナビゲーション**のみを外部ブラウザにリダイレクトしてください。

```dart theme={null}
import 'package:url_launcher/url_launcher.dart';

const allowedHost = 'my-domain.com';

_controller = WebViewController.fromPlatformCreationParams(params)
  ..setJavaScriptMode(JavaScriptMode.unrestricted)
  ..setNavigationDelegate(
    NavigationDelegate(
      onNavigationRequest: (NavigationRequest request) {
        final host = Uri.parse(request.url).host;

        // メインフレームのナビゲーションのみ外部ブラウザで開く
        // 広告リソース（例：googleads.g.doubleclick.net）はiframe/スクリプトでロードされるためブロックしない
        if (!host.contains(allowedHost) && request.isMainFrame) {
          launchUrl(Uri.parse(request.url), mode: LaunchMode.externalApplication);
          return NavigationDecision.prevent;
        }
        return NavigationDecision.navigate;
      },
    ),
  );
```

<Warning>
  自社ドメイン以外のすべてのリクエストをブロックまたはリダイレクトしないでください。`googleads.g.doubleclick.net`のような広告リソースはバックフィル広告のプロセスで自動的にロードされ、WebView内で正常にロードされる必要があります。
</Warning>

***

## 関連ドキュメント

<CardGroup cols={2}>
  <Card title="バナー広告" icon="rectangle-ad" href="/ja/sdk/flutter/banner">
    バナー広告の実装方法
  </Card>

  <Card title="リファレンス" icon="book" href="/ja/sdk/flutter/reference">
    APIリファレンス
  </Card>

  <Card title="サンプル" icon="code" href="/ja/sdk/flutter/examples">
    サンプルコード
  </Card>
</CardGroup>
