메인 콘텐츠로 건너뛰기

개요

팝업 광고는 화면 중앙 또는 하단에 팝업 형태로 표시되는 광고입니다. “오늘 하루 보지 않기” 기능을 지원하여 사용자 경험을 개선할 수 있습니다.

주요 특징

  • 화면 중앙 또는 하단 위치 선택 가능
  • “오늘 하루 보지 않기” 기능 지원
  • 버튼 색상 커스터마이징 가능
  • 이미지 광고 지원
개발 환경에서는 테스트 유닛 ID를 사용하세요:
  • 하단: PUBLIC_TEST_UNIT_ID_POPUP_BOTTOM
  • 중앙: PUBLIC_TEST_UNIT_ID_POPUP_CENTER

AdropPopupAd

생성자

AdropPopupAd({
  required String unitId,
  AdropPopupListener? listener,
  Color? closeTextColor,
  Color? hideForTodayTextColor,
  Color? backgroundColor,
})
파라미터
파라미터타입필수설명
unitIdStringY애드컨트롤 콘솔에서 생성한 유닛 ID
listenerAdropPopupListenerN광고 이벤트 리스너
closeTextColorColorN닫기 버튼 텍스트 색상
hideForTodayTextColorColorN”오늘 하루 보지 않기” 버튼 텍스트 색상
backgroundColorColorN버튼 배경 색상

속성

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

메서드

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

기본 사용법

import 'package:flutter/material.dart';
import 'package:adrop_ads_flutter/adrop_ads_flutter.dart';

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

  @override
  State<PopupExample> createState() => _PopupExampleState();
}

class _PopupExampleState extends State<PopupExample> {
  bool isLoaded = false;
  AdropPopupAd? popupAd;

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

  void _createPopupAd() {
    popupAd = AdropPopupAd(
      unitId: 'YOUR_UNIT_ID',
      listener: AdropPopupListener(
        onAdReceived: (ad) {
          debugPrint('팝업 광고 로드 성공: ${ad.creativeId}');
          setState(() {
            isLoaded = true;
          });
        },
        onAdFailedToReceive: (ad, errorCode) {
          debugPrint('팝업 광고 로드 실패: $errorCode');
        },
        onAdClicked: (ad) {
          debugPrint('팝업 광고 클릭');
        },
        onAdImpression: (ad) {
          debugPrint('팝업 광고 노출');
        },
        onAdDidPresentFullScreen: (ad) {
          debugPrint('팝업 광고 표시됨');
        },
        onAdDidDismissFullScreen: (ad) {
          debugPrint('팝업 광고 닫힘');
        },
        onAdFailedToShowFullScreen: (ad, errorCode) {
          debugPrint('팝업 광고 표시 실패: $errorCode');
        },
      ),
    );
  }

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

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

  @override
  void dispose() {
    popupAd?.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('광고 표시'),
            ),
          ],
        ),
      ),
    );
  }
}

AdropPopupListener

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

콜백 함수

AdropPopupListener(
  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광고 표시 실패 시 호출

버튼 색상 커스터마이징

팝업 광고의 닫기 버튼과 “오늘 하루 보지 않기” 버튼의 색상을 커스터마이징할 수 있습니다.
popupAd = AdropPopupAd(
  unitId: 'YOUR_UNIT_ID',
  // 닫기 버튼 텍스트 색상
  closeTextColor: Colors.white,
  // "오늘 하루 보지 않기" 버튼 텍스트 색상
  hideForTodayTextColor: Colors.white,
  // 버튼 배경 색상
  backgroundColor: Colors.black87,
  listener: AdropPopupListener(
    onAdReceived: (ad) {
      setState(() {
        isLoaded = true;
      });
    },
  ),
);

색상 옵션

파라미터설명기본값
closeTextColor닫기 버튼 텍스트 색상시스템 기본값
hideForTodayTextColor”오늘 하루 보지 않기” 버튼 텍스트 색상시스템 기본값
backgroundColor버튼 배경 색상시스템 기본값

팝업 위치

팝업 광고의 위치는 애드컨트롤 콘솔에서 유닛 생성 시 설정합니다.

중앙 팝업

화면 중앙에 팝업이 표시됩니다. 공지사항, 이벤트 알림 등에 적합합니다.
// 중앙 팝업용 유닛 ID 사용
popupAd = AdropPopupAd(
  unitId: 'YOUR_CENTER_POPUP_UNIT_ID',
  listener: AdropPopupListener(...),
);

하단 팝업

화면 하단에 팝업이 표시됩니다. 앱 실행 시 배너 형태의 알림에 적합합니다.
// 하단 팝업용 유닛 ID 사용
popupAd = AdropPopupAd(
  unitId: 'YOUR_BOTTOM_POPUP_UNIT_ID',
  listener: AdropPopupListener(...),
);

오늘 하루 보지 않기

사용자가 “오늘 하루 보지 않기”를 선택하면, 해당 기기에서 당일 자정까지 광고가 표시되지 않습니다.
“오늘 하루 보지 않기” 상태에서 광고를 로드하면 adHideForToday 에러가 반환됩니다.
onAdFailedToReceive: (ad, errorCode) {
  if (errorCode == AdropErrorCode.adHideForToday) {
    debugPrint('사용자가 오늘 하루 보지 않기를 선택했습니다.');
    // 광고 대신 다른 콘텐츠 표시
  }
}

광고 재생성

팝업 광고는 일회성입니다. 한 번 표시된 광고는 다시 표시할 수 없으므로, 새로운 광고를 로드하려면 인스턴스를 재생성해야 합니다.
class _PopupState extends State<PopupWidget> {
  bool isLoaded = false;
  bool isShown = false;
  AdropPopupAd? popupAd;

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

  void _createPopupAd() {
    popupAd?.dispose();
    popupAd = AdropPopupAd(
      unitId: 'YOUR_UNIT_ID',
      backgroundColor: Colors.black87,
      listener: AdropPopupListener(
        onAdReceived: (ad) {
          setState(() {
            isLoaded = true;
          });
        },
        onAdDidDismissFullScreen: (ad) {
          setState(() {
            isShown = true;
          });
          // 다음 표시를 위해 새 광고 준비
          _createPopupAd();
          popupAd?.load();
        },
      ),
    );

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

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

에러 처리

class _PopupState extends State<PopupWidget> {
  bool isLoaded = false;
  AdropErrorCode? errorCode;
  AdropPopupAd? popupAd;

  void _createPopupAd() {
    popupAd = AdropPopupAd(
      unitId: 'YOUR_UNIT_ID',
      listener: AdropPopupListener(
        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.adHideForToday:
        debugPrint('사용자가 오늘 하루 보지 않기를 선택했습니다.');
        break;
      case AdropErrorCode.adShown:
        debugPrint('이미 표시된 광고입니다.');
        break;
      default:
        debugPrint('오류 발생: ${error.code}');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: popupAd?.load,
          child: const Text('광고 로드'),
        ),
        ElevatedButton(
          onPressed: isLoaded ? popupAd?.show : null,
          child: const Text('광고 표시'),
        ),
        if (errorCode != null)
          Text(
            '에러: ${errorCode?.code}',
            style: const TextStyle(color: Colors.red),
          ),
      ],
    );
  }
}

베스트 프랙티스

1. 앱 시작 시 팝업 표시

앱 실행 시 공지사항이나 이벤트를 팝업으로 표시합니다.
class SplashScreen extends StatefulWidget {
  @override
  State<SplashScreen> createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  AdropPopupAd? popupAd;

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

  void _loadPopupAd() {
    popupAd = AdropPopupAd(
      unitId: 'YOUR_UNIT_ID',
      listener: AdropPopupListener(
        onAdReceived: (ad) {
          // 광고가 로드되면 표시
          popupAd?.show();
        },
        onAdFailedToReceive: (ad, errorCode) {
          // 광고 로드 실패 시 바로 메인 화면으로 이동
          if (errorCode != AdropErrorCode.adHideForToday) {
            _navigateToMain();
          }
        },
        onAdDidDismissFullScreen: (ad) {
          // 팝업 닫힌 후 메인 화면으로 이동
          _navigateToMain();
        },
      ),
    );
    popupAd?.load();
  }

  void _navigateToMain() {
    Navigator.of(context).pushReplacement(
      MaterialPageRoute(builder: (_) => const MainScreen()),
    );
  }

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

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: CircularProgressIndicator(),
      ),
    );
  }
}

2. 테마에 맞는 색상 사용

앱의 테마에 맞게 버튼 색상을 설정합니다.
void _createPopupAd() {
  final isDarkMode = Theme.of(context).brightness == Brightness.dark;

  popupAd = AdropPopupAd(
    unitId: 'YOUR_UNIT_ID',
    closeTextColor: isDarkMode ? Colors.white : Colors.black,
    hideForTodayTextColor: isDarkMode ? Colors.white70 : Colors.black54,
    backgroundColor: isDarkMode ? Colors.grey[800] : Colors.grey[200],
    listener: AdropPopupListener(...),
  );
}

3. 리소스 관리

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

전체 예제

import 'package:flutter/material.dart';
import 'package:adrop_ads_flutter/adrop_ads_flutter.dart';

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

  @override
  State<PopupAdPage> createState() => _PopupAdPageState();
}

class _PopupAdPageState extends State<PopupAdPage> {
  bool isLoaded = false;
  bool isLoading = false;
  bool isShown = false;
  AdropErrorCode? errorCode;
  AdropPopupAd? popupAd;

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

  void _createPopupAd() {
    popupAd?.dispose();
    popupAd = AdropPopupAd(
      unitId: 'PUBLIC_TEST_UNIT_ID_POPUP_BOTTOM', // 테스트 유닛 ID
      closeTextColor: Colors.white,
      hideForTodayTextColor: Colors.white70,
      backgroundColor: Colors.black87,
      listener: AdropPopupListener(
        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('광고 표시됨');
        },
        onAdWillDismissFullScreen: (ad) {
          debugPrint('광고 닫힘 예정');
        },
        onAdDidDismissFullScreen: (ad) {
          debugPrint('광고 닫힘');
          setState(() {
            isShown = true;
          });
        },
        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;
    });
    popupAd?.load();
  }

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

  @override
  void dispose() {
    popupAd?.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)
                    ? () => _createPopupAd()
                    : 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),
                ),
                if (errorCode == AdropErrorCode.adHideForToday)
                  const Text(
                    '(사용자가 오늘 하루 보지 않기를 선택했습니다)',
                    style: TextStyle(color: Colors.grey, fontSize: 12),
                  ),
              ],
            ],
          ),
        ),
      ),
    );
  }
}

다음 단계