메인 콘텐츠로 건너뛰기

개요

Adrop Flutter SDK의 예제 코드와 샘플 프로젝트를 확인하세요.

샘플 프로젝트

GitHub에서 전체 샘플 프로젝트를 확인할 수 있습니다.

Flutter 샘플 프로젝트

Dart로 작성된 Flutter 샘플 앱

빠른 시작 예제

배너 광고

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

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

  @override
  State<BannerAdExample> createState() => _BannerAdExampleState();
}

class _BannerAdExampleState extends State<BannerAdExample> {
  bool isLoaded = false;
  late AdropBannerView bannerView;

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

    bannerView = AdropBannerView(
      unitId: 'PUBLIC_TEST_UNIT_ID_320_100',
      listener: AdropBannerListener(
        onAdReceived: (unitId, metadata) {
          debugPrint('배너 광고 수신 성공: $unitId');
          setState(() => isLoaded = true);
        },
        onAdClicked: (unitId, metadata) {
          debugPrint('배너 광고 클릭: $unitId');
        },
        onAdFailedToReceive: (unitId, errorCode) {
          debugPrint('배너 광고 수신 실패: $errorCode');
        },
      ),
    );

    bannerView.load();
  }

  @override
  void dispose() {
    bannerView.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('배너 광고')),
      body: Column(
        children: [
          Expanded(
            child: Center(child: const Text('메인 콘텐츠')),
          ),
          if (isLoaded)
            SizedBox(
              width: MediaQuery.of(context).size.width,
              height: 80,
              child: bannerView,
            ),
        ],
      ),
    );
  }
}

네이티브 광고

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

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

  @override
  State<NativeAdExample> createState() => _NativeAdExampleState();
}

class _NativeAdExampleState extends State<NativeAdExample> {
  bool isLoaded = false;
  AdropNativeAd? nativeAd;

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

    nativeAd = AdropNativeAd(
      unitId: 'PUBLIC_TEST_UNIT_ID_NATIVE',
      listener: AdropNativeListener(
        onAdReceived: (ad) {
          debugPrint('네이티브 광고 수신: ${ad.creativeId}');
          setState(() => isLoaded = true);
        },
        onAdClicked: (ad) {
          debugPrint('네이티브 광고 클릭');
        },
        onAdFailedToReceive: (ad, errorCode) {
          debugPrint('네이티브 광고 수신 실패: $errorCode');
        },
      ),
    );

    nativeAd?.load();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('네이티브 광고')),
      body: SingleChildScrollView(
        child: Column(
          children: [
            const Padding(
              padding: EdgeInsets.all(16),
              child: Text('메인 콘텐츠'),
            ),
            if (isLoaded) _buildNativeAdView(),
          ],
        ),
      ),
    );
  }

  Widget _buildNativeAdView() {
    return AdropNativeAdView(
      ad: nativeAd,
      child: Container(
        margin: const EdgeInsets.all(16),
        padding: const EdgeInsets.all(16),
        decoration: BoxDecoration(
          border: Border.all(color: Colors.grey.shade300),
          borderRadius: BorderRadius.circular(8),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 프로필
            Row(
              children: [
                if (nativeAd?.properties.profile?.displayLogo != null)
                  ClipRRect(
                    borderRadius: BorderRadius.circular(12),
                    child: Image.network(
                      nativeAd!.properties.profile!.displayLogo!,
                      width: 24,
                      height: 24,
                    ),
                  ),
                const SizedBox(width: 8),
                Text(
                  nativeAd?.properties.profile?.displayName ?? '',
                  style: const TextStyle(
                    fontSize: 12,
                    color: Colors.grey,
                  ),
                ),
              ],
            ),
            const SizedBox(height: 12),
            // 헤드라인
            if (nativeAd?.properties.headline != null)
              Text(
                nativeAd!.properties.headline!,
                style: const TextStyle(
                  fontSize: 18,
                  fontWeight: FontWeight.bold,
                ),
              ),
            const SizedBox(height: 4),
            // 본문
            if (nativeAd?.properties.body != null)
              Text(
                nativeAd!.properties.body!,
                style: const TextStyle(
                  fontSize: 14,
                  color: Colors.grey,
                ),
              ),
            const SizedBox(height: 12),
            // 이미지
            if (nativeAd?.properties.asset != null)
              ClipRRect(
                borderRadius: BorderRadius.circular(8),
                child: Image.network(
                  nativeAd!.properties.asset!,
                  width: double.infinity,
                  fit: BoxFit.cover,
                ),
              ),
            const SizedBox(height: 12),
            // CTA 버튼
            if (nativeAd?.properties.callToAction != null)
              SizedBox(
                width: double.infinity,
                child: ElevatedButton(
                  onPressed: () {},
                  child: Text(nativeAd!.properties.callToAction!),
                ),
              ),
          ],
        ),
      ),
    );
  }
}

전면 광고

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

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

  @override
  State<InterstitialAdExample> createState() => _InterstitialAdExampleState();
}

class _InterstitialAdExampleState extends State<InterstitialAdExample> {
  bool isLoaded = false;
  AdropInterstitialAd? interstitialAd;

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

  void _createInterstitialAd() {
    interstitialAd?.dispose();
    interstitialAd = AdropInterstitialAd(
      unitId: 'PUBLIC_TEST_UNIT_ID_INTERSTITIAL',
      listener: AdropInterstitialListener(
        onAdReceived: (ad) {
          debugPrint('전면 광고 로드 완료');
          setState(() => isLoaded = true);
        },
        onAdClicked: (ad) {
          debugPrint('전면 광고 클릭');
        },
        onAdDidPresentFullScreen: (ad) {
          debugPrint('전면 광고 표시됨');
        },
        onAdDidDismissFullScreen: (ad) {
          debugPrint('전면 광고 닫힘');
          // 새 광고 로드
          _createInterstitialAd();
          interstitialAd?.load();
        },
        onAdFailedToReceive: (ad, errorCode) {
          debugPrint('전면 광고 로드 실패: $errorCode');
        },
      ),
    );

    setState(() => isLoaded = false);
  }

  @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: () => interstitialAd?.load(),
              child: const Text('광고 로드'),
            ),
            const SizedBox(height: 16),
            ElevatedButton(
              onPressed: isLoaded ? () => interstitialAd?.show() : null,
              child: const Text('광고 표시'),
            ),
          ],
        ),
      ),
    );
  }
}

리워드 광고

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

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

  @override
  State<RewardedAdExample> createState() => _RewardedAdExampleState();
}

class _RewardedAdExampleState extends State<RewardedAdExample> {
  bool isLoaded = false;
  int coins = 0;
  AdropRewardedAd? rewardedAd;

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

  void _createRewardedAd() {
    rewardedAd?.dispose();
    rewardedAd = AdropRewardedAd(
      unitId: 'PUBLIC_TEST_UNIT_ID_REWARDED',
      listener: AdropRewardedListener(
        onAdReceived: (ad) {
          debugPrint('리워드 광고 로드 완료');
          setState(() => isLoaded = true);
        },
        onAdDidDismissFullScreen: (ad) {
          debugPrint('리워드 광고 닫힘');
          // 새 광고 로드
          _createRewardedAd();
          rewardedAd?.load();
        },
        onAdEarnRewardHandler: (ad, type, amount) {
          debugPrint('보상 획득: type=$type, amount=$amount');
          setState(() => coins += amount);
          _showRewardSnackBar(amount);
        },
        onAdFailedToReceive: (ad, errorCode) {
          debugPrint('리워드 광고 로드 실패: $errorCode');
        },
      ),
    );

    setState(() => isLoaded = false);
  }

  void _showRewardSnackBar(int amount) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text('$amount 코인을 획득했습니다!'),
        backgroundColor: Colors.green,
      ),
    );
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('리워드 광고')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // 코인 표시
            Container(
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: Colors.amber.shade100,
                borderRadius: BorderRadius.circular(8),
              ),
              child: Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  const Icon(Icons.monetization_on, color: Colors.amber),
                  const SizedBox(width: 8),
                  Text(
                    '$coins 코인',
                    style: const TextStyle(
                      fontSize: 24,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ],
              ),
            ),
            const SizedBox(height: 32),
            ElevatedButton(
              onPressed: () => rewardedAd?.load(),
              child: const Text('광고 로드'),
            ),
            const SizedBox(height: 16),
            ElevatedButton.icon(
              onPressed: isLoaded ? () => rewardedAd?.show() : null,
              icon: const Icon(Icons.play_circle_outline),
              label: const Text('광고 보고 보상 받기'),
              style: ElevatedButton.styleFrom(
                backgroundColor: isLoaded ? Colors.green : Colors.grey,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

팝업 광고

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

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

  @override
  State<PopupAdExample> createState() => _PopupAdExampleState();
}

class _PopupAdExampleState extends State<PopupAdExample> {
  bool isLoaded = false;
  AdropPopupAd? popupAd;

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

  void _createPopupAd() {
    popupAd?.dispose();
    popupAd = AdropPopupAd(
      unitId: 'PUBLIC_TEST_UNIT_ID_POPUP_BOTTOM',
      closeTextColor: Colors.white,
      hideForTodayTextColor: Colors.white70,
      backgroundColor: Colors.black87,
      listener: AdropPopupListener(
        onAdReceived: (ad) {
          debugPrint('팝업 광고 로드 완료');
          setState(() => isLoaded = true);
        },
        onAdDidDismissFullScreen: (ad) {
          debugPrint('팝업 광고 닫힘');
          _createPopupAd();
        },
        onAdFailedToReceive: (ad, errorCode) {
          debugPrint('팝업 광고 로드 실패: $errorCode');
          if (errorCode == AdropErrorCode.adHideForToday) {
            debugPrint('사용자가 오늘 하루 보지 않기를 선택했습니다.');
          }
        },
      ),
    );

    setState(() => isLoaded = false);
  }

  @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: () => popupAd?.load(),
              child: const Text('광고 로드'),
            ),
            const SizedBox(height: 16),
            ElevatedButton(
              onPressed: isLoaded ? () => popupAd?.show() : null,
              child: const Text('광고 표시'),
            ),
          ],
        ),
      ),
    );
  }
}

고급 예제

다크 모드 지원

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

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _initializeAdrop();
  }

  Future<void> _initializeAdrop() async {
    await Adrop.initialize(true);

    // 시스템 테마에 따라 자동 설정
    await Adrop.setTheme(AdropTheme.auto);
  }

  @override
  void didChangePlatformBrightness() {
    // 시스템 테마 변경 감지 시 처리
    // AdropTheme.auto 사용 시 자동으로 처리됨
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      themeMode: ThemeMode.system,
      theme: ThemeData.light(),
      darkTheme: ThemeData.dark(),
      home: const HomeScreen(),
    );
  }
}

사용자 타겟팅 설정

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

class UserProfileScreen extends StatelessWidget {
  final User user;

  const UserProfileScreen({super.key, required this.user});

  Future<void> _setupTargeting() async {
    // UID 설정
    await Adrop.setUID(user.id);

    // 기본 속성 설정
    await AdropMetrics.setProperty('birth', user.birthDate);
    await AdropMetrics.setProperty('gender', user.gender);

    // 커스텀 속성 설정
    await AdropMetrics.setProperty('membership_level', user.membershipLevel);
    await AdropMetrics.setProperty('total_purchase', user.totalPurchase);
    await AdropMetrics.setProperty('is_premium', user.isPremium);

    // 이벤트 로깅
    await AdropMetrics.logEvent('profile_view', {
      'user_id': user.id,
      'membership': user.membershipLevel,
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('프로필')),
      body: Center(
        child: ElevatedButton(
          onPressed: _setupTargeting,
          child: const Text('타겟팅 설정'),
        ),
      ),
    );
  }
}

class User {
  final String id;
  final String birthDate;
  final String gender;
  final String membershipLevel;
  final int totalPurchase;
  final bool isPremium;

  User({
    required this.id,
    required this.birthDate,
    required this.gender,
    required this.membershipLevel,
    required this.totalPurchase,
    required this.isPremium,
  });
}

광고 미리 로드

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

class AdPreloader {
  static AdropInterstitialAd? _interstitialAd;
  static AdropRewardedAd? _rewardedAd;
  static bool _isInterstitialReady = false;
  static bool _isRewardedReady = false;

  static void preloadInterstitial() {
    _interstitialAd?.dispose();
    _interstitialAd = AdropInterstitialAd(
      unitId: 'YOUR_INTERSTITIAL_UNIT_ID',
      listener: AdropInterstitialListener(
        onAdReceived: (ad) {
          _isInterstitialReady = true;
          debugPrint('전면 광고 준비 완료');
        },
        onAdDidDismissFullScreen: (ad) {
          _isInterstitialReady = false;
          // 다음을 위해 다시 로드
          Future.delayed(const Duration(seconds: 1), preloadInterstitial);
        },
        onAdFailedToReceive: (ad, errorCode) {
          _isInterstitialReady = false;
          // 재시도
          Future.delayed(const Duration(seconds: 5), preloadInterstitial);
        },
      ),
    );
    _interstitialAd?.load();
  }

  static void preloadRewarded() {
    _rewardedAd?.dispose();
    _rewardedAd = AdropRewardedAd(
      unitId: 'YOUR_REWARDED_UNIT_ID',
      listener: AdropRewardedListener(
        onAdReceived: (ad) {
          _isRewardedReady = true;
          debugPrint('리워드 광고 준비 완료');
        },
        onAdDidDismissFullScreen: (ad) {
          _isRewardedReady = false;
          Future.delayed(const Duration(seconds: 1), preloadRewarded);
        },
        onAdFailedToReceive: (ad, errorCode) {
          _isRewardedReady = false;
          Future.delayed(const Duration(seconds: 5), preloadRewarded);
        },
      ),
    );
    _rewardedAd?.load();
  }

  static bool get isInterstitialReady => _isInterstitialReady;
  static bool get isRewardedReady => _isRewardedReady;

  static void showInterstitial() {
    if (_isInterstitialReady) {
      _interstitialAd?.show();
      _isInterstitialReady = false;
    }
  }

  static void showRewarded(
      void Function(int type, int amount)? onEarnReward) {
    if (_isRewardedReady) {
      if (onEarnReward != null) {
        _rewardedAd = AdropRewardedAd(
          unitId: 'YOUR_REWARDED_UNIT_ID',
          listener: AdropRewardedListener(
            onAdEarnRewardHandler: (ad, type, amount) {
              onEarnReward(type, amount);
            },
            onAdDidDismissFullScreen: (ad) {
              _isRewardedReady = false;
              preloadRewarded();
            },
          ),
        );
      }
      _rewardedAd?.show();
      _isRewardedReady = false;
    }
  }

  static void dispose() {
    _interstitialAd?.dispose();
    _rewardedAd?.dispose();
    _interstitialAd = null;
    _rewardedAd = null;
    _isInterstitialReady = false;
    _isRewardedReady = false;
  }
}

// 앱 시작 시 호출
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Adrop.initialize(true);

  // 광고 미리 로드
  AdPreloader.preloadInterstitial();
  AdPreloader.preloadRewarded();

  runApp(const MyApp());
}

관련 문서