메인 콘텐츠로 건너뛰기

개요

전면 광고는 화면 전체를 덮는 풀스크린 광고입니다. 자연스러운 전환 시점(예: 게임 레벨 완료, 페이지 이동 등)에 표시하면 효과적입니다.

주요 특징

  • 화면 전체를 덮는 풀스크린 광고
  • 이미지 및 동영상 광고 지원
  • 풀스크린 이벤트 콜백 제공
  • 로드와 표시를 분리하여 유연한 타이밍 제어
개발 환경에서는 테스트 유닛 ID를 사용하세요: PUBLIC_TEST_UNIT_ID_INTERSTITIAL

AdropInterstitialAd

생성자

AdropInterstitialAd({
  required String unitId,
  AdropInterstitialListener? listener,
})
파라미터
파라미터타입필수설명
unitIdStringY애드컨트롤 콘솔에서 생성한 유닛 ID
listenerAdropInterstitialListenerN광고 이벤트 리스너

속성

속성타입설명
isLoadedbool광고 로드 완료 여부
unitIdString광고 유닛 ID
creativeIdString크리에이티브 ID
txIdString트랜잭션 ID
campaignIdString캠페인 ID
destinationURLString목적지 URL

메서드

메서드반환 타입설명
load()Future<void>광고를 로드합니다
show()Future<void>광고를 화면에 표시합니다
dispose()Future<void>리소스를 해제합니다

기본 사용법

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');
        },
      ),
    );
  }

  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

전면 광고 이벤트를 처리하는 리스너입니다.

콜백 함수

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) {
    // 광고 표시 실패
  },
)

콜백 설명

콜백설명
onAdReceived광고 로드 성공 시 호출
onAdClicked광고 클릭 시 호출
onAdImpression광고 노출 시 호출
onAdWillPresentFullScreen광고가 표시되기 직전 호출 (iOS 전용)
onAdDidPresentFullScreen광고가 표시된 후 호출
onAdWillDismissFullScreen광고가 닫히기 직전 호출 (iOS 전용)
onAdDidDismissFullScreen광고가 닫힌 후 호출
onAdFailedToReceive광고 로드 실패 시 호출
onAdFailedToShowFullScreen광고 표시 실패 시 호출

광고 라이프사이클


광고 재생성

전면 광고는 일회성입니다. 한 번 표시된 광고는 다시 표시할 수 없으므로, 새로운 광고를 로드하려면 인스턴스를 재생성해야 합니다.
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();
  }
}

에러 처리

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. 적절한 타이밍에 표시

전면 광고는 자연스러운 전환 시점에 표시하세요.
// 좋은 예: 레벨 완료 후
void onLevelComplete() {
  showInterstitialAd();
  navigateToNextLevel();
}

// 나쁜 예: 앱 시작 직후
void onAppStart() {
  showInterstitialAd(); // 사용자 경험 저하
}

2. 미리 로드하기

광고를 미리 로드해두면 표시 시점에 지연 없이 보여줄 수 있습니다.
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. 빈도 제한

사용자 경험을 위해 광고 표시 빈도를 제한하세요.
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. 리소스 관리

사용하지 않는 광고 인스턴스는 반드시 해제하세요.
@override
void dispose() {
  interstitialAd?.dispose();
  super.dispose();
}

전체 예제

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;
          });
        },
      ),
    );

    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),
                ),
              ],
            ],
          ),
        ),
      ),
    );
  }
}

다음 단계