1. 소개
이 Codelab에서는 Flutter 앱에 AdMob 배너 및 AdMob 네이티브 인라인 광고를 구현합니다.
빌드할 항목
이 Codelab은 Flutter용 Google 모바일 광고 플러그인을 사용하여 Flutter 앱에 AdMob 인라인 배너 및 AdMob 네이티브 인라인 광고를 구현하는 방법을 안내합니다.
이 Codelab을 진행하는 동안 코드 버그, 문법 오류, 불명확한 문구 등의 문제가 발생하면 Codelab 왼쪽 하단에 있는 오류 신고 링크를 통해 신고해 주세요.
학습 내용
- Google 모바일 광고 Flutter 플러그인 구성 방법
- Flutter 앱의 인라인 배너 및 보상형 광고 구현 방법
필요한 항목
- Android 스튜디오 4.1 이상
- Xcode 12 이상(iOS 개발용)
AdMob 사용 경험 수준을 평가해 주세요.
Flutter 사용 경험 수준을 평가해 주세요.
<ph type="x-smartling-placeholder">2. Flutter 개발 환경 설정
이 실습을 완료하려면 Flutter SDK 및 편집기라는 두 가지 소프트웨어가 필요합니다.
다음 기기 중 하나를 사용하여 이 Codelab을 실행할 수 있습니다.
- 컴퓨터에 연결되어 있으며 개발자 모드로 설정된 실제 Android 또는 iOS 기기
- iOS 시뮬레이터(Xcode 도구 설치 필요)
- Android Emulator(Android 스튜디오 설정 필요)
- 브라우저(디버깅 시 Chrome 필요)
- Windows, Linux 또는 macOS 데스크톱 애플리케이션. 배포에 사용할 플랫폼에서 개발해야 합니다. 따라서 Windows 데스크톱 앱을 개발하려면 적절한 빌드 체인에 액세스할 수 있도록 Windows에서 개발해야 합니다. docs.flutter.dev/desktop에 운영체제별 요구사항이 자세히 설명되어 있습니다.
코드 다운로드
zip 파일을 다운로드한 후 콘텐츠의 압축을 풉니다. 이름이 admob-inline-ads-in-flutter-main
인 폴더가 생성됩니다.
또는 명령줄에서 GitHub 저장소를 클론할 수 있습니다.
$ git clone https://github.com/googlecodelabs/admob-inline-ads-in-flutter
저장소에는 다음과 같은 폴더 세 개가 있습니다.
- starter: 이 Codelab에서 빌드할 시작 코드입니다.
- complete: 이 Codelab의 완성된 코드입니다. (네이티브 코드의 경우 자바 및 Objective-C)
- complete_kotlin_swift: 이 Codelab의 완성된 코드입니다. (네이티브 코드의 경우 Kotlin 및 Swift)
3. AdMob 앱 및 광고 단위 설정
Flutter는 멀티 플랫폼 SDK이므로 AdMob에서 Android와 iOS에 모두 앱과 광고 단위를 추가해야 합니다.
Android 설정
Android에 맞춰 설정하려면 Android 앱을 추가하고 광고 단위를 만들어야 합니다.
Android 앱 추가
- AdMob 콘솔의 앱 메뉴에서 앱 추가를 클릭합니다.
- 앱을 Google Play 또는 App Store에 게시하셨나요?라는 메시지가 표시되면 아니요를 클릭합니다.
- 앱 이름 필드에
AdMob inline ads
를 입력하고 플랫폼으로 Android를 선택합니다.
- 이 Codelab을 완료하기 위해 사용자 측정항목을 사용할 필요는 없습니다. 하지만 사용자 행동을 더 자세히 이해할 수 있으므로 사용하는 것이 좋습니다. 추가를 클릭하여 절차를 완료합니다.
광고 단위 만들기
광고 단위를 추가하려면 다음 단계를 따릅니다.
- AdMob 콘솔의 앱 메뉴에서 AdMob 인라인 광고 앱을 선택합니다.
- 광고 단위 메뉴를 클릭합니다.
배너
|
네이티브
|
새 광고 단위에서 광고를 게재할 수 있으려면 보통 몇 시간이 걸립니다.
광고의 작동 방식을 즉시 테스트하려면 Android 앱 ID/광고 단위 ID 및 iOS 앱 ID/광고 단위 ID 표에 표시된 테스트 앱 ID와 광고 단위 ID를 사용하세요.
iOS용 설정
iOS에 맞춰 설정하려면 iOS 앱을 추가하고 광고 단위를 만들어야 합니다.
iOS 앱 추가
- AdMob 콘솔의 앱 메뉴에서 앱 추가를 클릭합니다.
- 앱을 Google Play 또는 App Store에 게시하셨나요?라는 메시지가 표시되면 아니요를 클릭합니다.
- 앱 이름 필드에
AdMob inline ads
를 입력하고 플랫폼으로 iOS를 선택합니다.
- 이 Codelab을 완료하기 위해 사용자 측정항목을 사용할 필요는 없습니다. 하지만 사용자 행동을 더 자세히 이해할 수 있으므로 사용하는 것이 좋습니다. 추가를 클릭하여 절차를 완료합니다.
광고 단위 만들기
광고 단위를 추가하려면 다음 단계를 따릅니다.
- AdMob 콘솔의 앱 메뉴에서 AdMob 인라인 광고 앱을 선택합니다.
- 광고 단위 메뉴를 클릭합니다.
배너
|
네이티브
|
새 광고 단위에서 광고를 게재할 수 있으려면 보통 몇 시간이 걸립니다.
광고의 동작을 즉시 테스트하려면 다음 표에 나와 있는 테스트 앱 ID와 광고 단위 ID를 사용하세요.
선택사항: 테스트 AdMob 앱 및 광고 단위 사용
새 애플리케이션과 광고 단위를 직접 만드는 대신 Codelab을 따르려면 다음 표에 나온 테스트 AdMob 앱 ID와 광고 단위 ID를 사용하세요.
Android 앱 ID/광고 단위 ID
항목 | 앱 ID/광고 단위 ID |
AdMob 앱 ID |
|
배너 |
|
네이티브 |
|
iOS 앱 ID/광고 단위 ID
항목 | 앱 ID/광고 단위 ID |
AdMob 앱 ID |
|
배너 |
|
네이티브 |
|
테스트 광고에 대한 자세한 내용은 Android 테스트 광고 및 iOS 테스트 광고 개발자 설명서를 참고하세요.
4. Google 모바일 광고 Flutter 플러그인 추가
Flutter는 플러그인을 사용하여 다양한 플랫폼별 서비스에 액세스할 권한을 제공합니다. 플러그인을 사용하면 각 플랫폼에서 서비스와 API에 액세스할 수 있습니다.
google_mobile_ads 플러그인은 AdMob API를 사용하여 배너, 전면 광고, 보상형 광고, 네이티브 광고의 로드 및 표시를 지원합니다.
Flutter는 멀티 플랫폼 SDK이므로 google_mobile_ads 플러그인을 iOS와 Android에 모두 적용할 수 있습니다. 따라서 플러그인을 Flutter 앱에 추가하면 AdMob 인라인 광고 앱의 Android 및 iOS 버전 모두에 사용됩니다.
Google 모바일 광고 플러그인을 종속 항목으로 추가
AdMob 인라인 광고 프로젝트에서 AdMob API에 액세스하려면 google_mobile_ads
를 프로젝트의 루트에 있는 pubspec.yaml
파일에 종속 항목으로 추가합니다.
pubspec.yaml
...
dependencies:
flutter:
sdk: flutter
google_fonts: ^0.3.9
# TODO: Add google_mobile_ads as a dependency
google_mobile_ads: ^1.2.0
...
Pub get(Pub 받기)을 클릭하여 AdMob 인라인 광고 프로젝트에 플러그인을 설치합니다.
AndroidManifest.xml 업데이트(Android)
- Android 스튜디오에서
android/app/src/main/AndroidManifest.xml
파일을 엽니다. - 이름이
com.google.android.gms.ads.APPLICATION_ID
인<meta-data>
태그를 추가하여 AdMob 앱 ID를 추가합니다. 예를 들어 AdMob 앱 ID가ca-app-pub-3940256099942544~3347511713
인 경우AndroidManifest.xml
파일에 다음 행을 추가해야 합니다.
AndroidManifest.xml
<manifest>
...
<application>
...
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-3940256099942544~3347511713"/>
</application>
</manifest>
Info.plist 업데이트(iOS)
- Android 스튜디오에서
ios/Runner/Info.plist
파일을 엽니다. - AdMob 앱 ID의 문자열 값이 포함된
GADApplicationIdentifier
키를 추가합니다. 예를 들어 AdMob 앱 ID가ca-app-pub-3940256099942544~1458002511
인 경우Info.plist
파일에 다음 행을 추가해야 합니다.
ios/Runner/Info.plist
...
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-3940256099942544~1458002511</string>
...
5. 광고의 도우미 클래스 추가
lib
디렉터리에 ad_helper.dart
라는 새 파일을 만듭니다. 그런 다음 AdMob 앱 ID와 Android 및 iOS용 광고 단위 ID를 제공하는 AdHelper
클래스를 구현합니다.
AdMob 앱 ID(ca-app-pub-xxxxxx~yyyyy
)와 광고 단위 ID(ca-app-pub-xxxxxxx/yyyyyyyy
)를 이전 단계에서 만든 ID로 바꿔야 합니다.
ad_helper.dart
import 'dart:io';
class AdHelper {
static String get bannerAdUnitId {
if (Platform.isAndroid) {
return "<YOUR_ANDROID_BANNER_AD_UNIT_ID";
} else if (Platform.isIOS) {
return "<YOUR_IOS_BANNER_AD_UNIT_ID>";
} else {
throw UnsupportedError("Unsupported platform");
}
}
static String get nativeAdUnitId {
if (Platform.isAndroid) {
return "<YOUR_ANDROID_NATIVE_AD_UNIT_ID>";
} else if (Platform.isIOS) {
return "<YOUR_IOS_NATIVE_AD_UNIT_ID>";
} else {
throw UnsupportedError("Unsupported platform");
}
}
}
테스트 AdMob 앱 ID와 테스트 광고 단위 ID를 사용하려면 다음 코드 스니펫을 사용합니다.
ad_helper.dart
import 'dart:io';
class AdHelper {
static String get bannerAdUnitId {
if (Platform.isAndroid) {
return 'ca-app-pub-3940256099942544/6300978111';
} else if (Platform.isIOS) {
return 'ca-app-pub-3940256099942544/2934735716';
}
throw UnsupportedError("Unsupported platform");
}
static String get nativeAdUnitId {
if (Platform.isAndroid) {
return 'ca-app-pub-3940256099942544/2247696110';
} else if (Platform.isIOS) {
return 'ca-app-pub-3940256099942544/3986624511';
}
throw UnsupportedError("Unsupported platform");
}
}
6. Google 모바일 광고 SDK 초기화
광고를 로드하기 전에 Google 모바일 광고 SDK를 초기화해야 합니다. lib/home_page.dart
파일을 열고 _initGoogleMobileAds()
를 수정하여 SDK를 초기화한 다음 홈페이지를 로드합니다.
SDK 초기화가 완료된 후에 결과를 가져오려면 _initGoogleMobileAds()
메서드의 반환 유형을 Future<dynamic>
에서 Future<InitializationStatus>
로 변경해야 합니다.
home_page.dart
// TODO: Import google_mobile_ads.dart
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:flutter/material.dart';
...
class HomePage extends StatelessWidget {
...
Future<InitializationStatus> _initGoogleMobileAds() {
// TODO: Initialize Google Mobile Ads SDK
return MobileAds.instance.initialize();
}
}
7. 배너 광고 추가
이 섹션에서는 다음 스크린샷과 같이 목록 중간에 배너 광고를 표시합니다.
lib/banner_inline_page.dart
파일을 엽니다.- 다음 행을 추가하여
ad_helper.dart
와google_mobile_ads.dart
를 가져옵니다.
banner_inline_page.dart
...
// TODO: Import ad_helper.dart
import 'package:admob_inline_ads_in_flutter/ad_helper.dart';
// TODO: Import google_mobile_ads.dart
import 'package:google_mobile_ads/google_mobile_ads.dart';
class BannerInlinePage extends StatefulWidget {
...
}
_BannerInlinePageState
클래스에서 배너 광고에 다음 멤버와 메서드를 추가합니다.
_kAdIndex
는 배너 광고가 표시될 인덱스를 나타내며 _getDestinationItemIndex()
메서드에서 항목 인덱스를 계산하는 데 사용됩니다.
banner_inline_page.dart
class _BannerInlinePageState extends State<BannerInlinePage> {
// TODO: Add _kAdIndex
static final _kAdIndex = 4;
// TODO: Add a banner ad instance
BannerAd? _ad;
...
// TODO: Add _getDestinationItemIndex()
int _getDestinationItemIndex(int rawIndex) {
if (rawIndex >= _kAdIndex && _ad != null) {
return rawIndex - 1;
}
return rawIndex;
}
...
}
initState()
메서드에서 320x50 배너 (AdSize.banner
)의BannerAd
를 만들고 로드합니다. 광고 이벤트 리스너는 광고가 로드될 때 UI (setState()
)를 업데이트하도록 구성됩니다.
banner_inline_page.dart
@override
void initState() {
super.initState();
// TODO: Load a banner ad
BannerAd(
adUnitId: AdHelper.bannerAdUnitId,
size: AdSize.banner,
request: AdRequest(),
listener: BannerAdListener(
onAdLoaded: (ad) {
setState(() {
_ad = ad as BannerAd;
});
},
onAdFailedToLoad: (ad, error) {
// Releases an ad resource when it fails to load
ad.dispose();
print('Ad load failed (code=${error.code} message=${error.message})');
},
),
).load();
}
- 가능한 경우 배너 광고를 표시하도록
build()
메서드를 수정합니다. itemCount,
를 업데이트하여 배너 광고 항목을 계산하고itemBuilder,
를 업데이트하여 광고가 로드될 때 광고 인덱스(_kAdIndex
)에서 배너 광고를 렌더링합니다._getDestinationItemIndex()
메서드를 사용하여 콘텐츠 항목의 인덱스를 가져오도록 코드를 업데이트합니다.
banner_inline_page.dart
@override
Widget build(BuildContext context) {
return Scaffold(
...
body: ListView.builder(
// TODO: Adjust itemCount based on the ad load state
itemCount: widget.entries.length + (_ad != null ? 1 : 0),
itemBuilder: (context, index) {
// TODO: Render a banner ad
if (_ad != null && index == _kAdIndex) {
return Container(
width: _ad!.size.width.toDouble(),
height: 72.0,
alignment: Alignment.center,
child: AdWidget(ad: _ad!),
);
} else {
// TODO: Get adjusted item index from _getDestinationItemIndex()
final item = widget.entries[_getDestinationItemIndex(index)];
return ListTile(
...
);
}
},
),
);
}
dispose()
콜백 메서드에서BannerAd.dispose()
메서드를 호출하여BannerAd
객체와 연결된 리소스를 해제합니다.
banner_inline_page.dart
@override
void dispose() {
// TODO: Dispose a BannerAd object
_ad?.dispose();
super.dispose();
}
이제 완료됐습니다. 프로젝트를 실행하고 홈페이지에서 Banner inline ad(배너 인라인 광고) 버튼을 클릭합니다. 광고가 로드되면 목록 중간에 배너 광고가 표시됩니다.
8. 네이티브 광고 추가
이 섹션에서는 다음 스크린샷과 같이 목록 중간에 네이티브 광고를 표시합니다.
네이티브 광고는 Android의 View
또는 iOS의 UIView
와 같이 플랫폼의 네이티브인 UI 구성요소를 사용하여 사용자에게 표시됩니다.
그러나 Flutter 위젯을 사용하여 네이티브 UI 구성요소를 직접 생성할 수는 없습니다. 따라서 네이티브 광고 객체(Android의 NativeAd
, iOS의 GADNativeAd
)에서 플랫폼별 네이티브 광고 뷰(Android의 NativeAdView
, iOS의 GADNativeAdView
)를 빌드하는 데 사용되는 각 플랫폼의 NativeAdFactory
를 구현해야 합니다.
Android용 NativeAdFactory 구현(자바)
android/build.gradle
파일 또는 android 폴더의 파일을 열고 Open for Editing in Android Studio(편집을 위해 Android Studio에서 열기)를 클릭하여 Android 프로젝트를 엽니다.
- 새 프로젝트를 열 창을 선택하라는 메시지가 표시되면 New Window(새 창)를 클릭하여 Android 프로젝트에서 작업하는 동안 Flutter 프로젝트를 열어 둡니다.
네이티브 광고 레이아웃 만들기
- Android 프로젝트를 열고 Android 스튜디오의 프로젝트 창에서 앱을 마우스 오른쪽 버튼으로 클릭한 다음 컨텍스트 메뉴에서 New > Android Resource File을 선택합니다.
- New Resource File 대화상자에
list_tile_native_ad.xml
을 파일 이름으로 입력합니다. - 리소스 유형으로 Layout을 선택하고
com.google.android.gms.ads.nativead.NativeAdView
를 루트 요소로 입력합니다. - OK를 클릭하여 새 레이아웃 파일을 만듭니다.
- 다음과 같이 광고 레이아웃을 구현합니다. 레이아웃은 대상 플랫폼 사용자 환경의 시각적 디자인과 일치해야 합니다.
list_tile_native_ad.xml
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.ads.nativead.NativeAdView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_list_tile_native_ad_attribution_small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#F19938"
android:text="Ad"
android:textColor="#FFFFFF"
android:textSize="12sp" />
<ImageView
android:id="@+id/iv_list_tile_native_ad_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:scaleType="fitXY"
tools:background="#EDEDED" />
<TextView
android:id="@+id/tv_list_tile_native_ad_attribution_large"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:background="#F19938"
android:gravity="center"
android:text="Ad"
android:textColor="#FFFFFF"
android:visibility="invisible" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="80dp"
android:layout_marginLeft="80dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_list_tile_native_ad_headline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:textColor="#000000"
android:textSize="16sp"
tools:text="Headline" />
<TextView
android:id="@+id/tv_list_tile_native_ad_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:textColor="#828282"
android:textSize="14sp"
tools:text="body" />
</LinearLayout>
</FrameLayout>
</com.google.android.gms.ads.nativead.NativeAdView>
ListTileNativeAdFactory 클래스 만들기
- 프로젝트 창에서 com.codelab.flutter.admobinlineads 패키지를 마우스 오른쪽 버튼으로 클릭하고 New > Java Class를 선택합니다.
ListTileNativeAdFactory
를 이름으로 입력하고 목록에서 Class를 선택합니다.
- New Class 대화상자가 나타나면 모든 항목을 비워 두고 OK를 클릭합니다.
com.codelab.flutter.admobinlineads
패키지에 ListTileNativeAdFactory
클래스가 생성되었음을 확인할 수 있습니다.
- 다음과 같이
ListTileNativeAdFactory
클래스를 구현합니다. 이 클래스는GoogleMobileAdsPlugin.NativeAdFactory
인터페이스에서createNativeAd()
메서드를 구현합니다.
Factory 클래스는 네이티브 광고를 렌더링하기 위한 뷰 객체를 생성합니다. 코드에서 알 수 있듯이 Factory 클래스는 UnifiedNativeAdView
를 생성하고 NativeAd
객체로 채웁니다.
ListTileNativeAdFactory.java
// TODO: Implement ListTileNativeAdFactory class
package com.codelab.flutter.admobinlineads;
import com.google.android.gms.ads.nativead.NativeAd;
import com.google.android.gms.ads.nativead.NativeAdView;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.Map;
import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin;
class ListTileNativeAdFactory implements GoogleMobileAdsPlugin.NativeAdFactory {
private final Context context;
ListTileNativeAdFactory(Context context) {
this.context = context;
}
@Override
public NativeAdView createNativeAd(
NativeAd nativeAd, Map<String, Object> customOptions) {
NativeAdView nativeAdView = (NativeAdView) LayoutInflater.from(context)
.inflate(R.layout.list_tile_native_ad, null);
TextView attributionViewSmall = nativeAdView
.findViewById(R.id.tv_list_tile_native_ad_attribution_small);
TextView attributionViewLarge = nativeAdView
.findViewById(R.id.tv_list_tile_native_ad_attribution_large);
ImageView iconView = nativeAdView.findViewById(R.id.iv_list_tile_native_ad_icon);
NativeAd.Image icon = nativeAd.getIcon();
if (icon != null) {
attributionViewSmall.setVisibility(View.VISIBLE);
attributionViewLarge.setVisibility(View.INVISIBLE);
iconView.setImageDrawable(icon.getDrawable());
} else {
attributionViewSmall.setVisibility(View.INVISIBLE);
attributionViewLarge.setVisibility(View.VISIBLE);
}
nativeAdView.setIconView(iconView);
TextView headlineView = nativeAdView.findViewById(R.id.tv_list_tile_native_ad_headline);
headlineView.setText(nativeAd.getHeadline());
nativeAdView.setHeadlineView(headlineView);
TextView bodyView = nativeAdView.findViewById(R.id.tv_list_tile_native_ad_body);
bodyView.setText(nativeAd.getBody());
bodyView.setVisibility(nativeAd.getBody() != null ? View.VISIBLE : View.INVISIBLE);
nativeAdView.setBodyView(bodyView);
nativeAdView.setNativeAd(nativeAd);
return nativeAdView;
}
}
ListTileNativeAdFactory 클래스 등록
NativeAdFactory
의 인스턴스를 Flutter 측에서 사용하려면 GoogleMobileAdsPlugin
에 등록해야 합니다.
MainActivity.java
파일을 열고configureFlutterEngine()
메서드와cleanUpFlutterEngine()
메서드를 재정의합니다.configureFlutterEngine()
메서드에서 고유한 문자열 ID(listTile
)를 사용하여ListTileNativeAdFactory
클래스를 등록합니다.
MainActivity.java
public class MainActivity extends FlutterActivity {
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
// TODO: Register the ListTileNativeAdFactory
GoogleMobileAdsPlugin.registerNativeAdFactory(flutterEngine, "listTile",
new ListTileNativeAdFactory(getContext()));
}
...
}
- 정리 프로세스 중에 모든
NativeAdFactory
인스턴스를 등록 취소해야 합니다.cleanUpFlutterEngine()
메서드에서ListTileNativeAdFactory
클래스를 등록 취소합니다.
MainActivity.java
public class MainActivity extends FlutterActivity {
...
@Override
public void cleanUpFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.cleanUpFlutterEngine(flutterEngine);
// TODO: Unregister the ListTileNativeAdFactory
GoogleMobileAdsPlugin.unregisterNativeAdFactory(flutterEngine, "listTile");
}
}
이제 ListTileNativeAdFactory
클래스를 사용하여 Android에서 네이티브 광고를 렌더링할 준비가 되었습니다.
Android용 NativeAdFactory 구현(Kotlin)
android/build.gradle
파일 또는 android 폴더의 파일을 열고 Open for Editing in Android Studio(편집을 위해 Android Studio에서 열기)를 클릭하여 Android 프로젝트를 엽니다.
- 새 프로젝트를 열 창을 선택하라는 메시지가 표시되면 New Window(새 창)를 클릭하여 Android 프로젝트에서 작업하는 동안 Flutter 프로젝트를 열어 둡니다.
네이티브 광고 레이아웃 만들기
- Android 프로젝트를 열고 Android 스튜디오의 프로젝트 창에서 앱을 마우스 오른쪽 버튼으로 클릭한 다음 컨텍스트 메뉴에서 New > Android Resource File을 선택합니다.
- New Resource File 대화상자에
list_tile_native_ad.xml
을 파일 이름으로 입력합니다. - 리소스 유형으로 Layout을 선택하고
com.google.android.gms.ads.nativead.NativeAdView
를 루트 요소로 입력합니다. - OK를 클릭하여 새 레이아웃 파일을 만듭니다.
- 다음과 같이 광고 레이아웃을 구현합니다. 레이아웃은 대상 플랫폼 사용자 환경의 시각적 디자인과 일치해야 합니다.
list_tile_native_ad.xml
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.ads.nativead.NativeAdView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_list_tile_native_ad_attribution_small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#F19938"
android:text="Ad"
android:textColor="#FFFFFF"
android:textSize="12sp" />
<ImageView
android:id="@+id/iv_list_tile_native_ad_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:scaleType="fitXY"
tools:background="#EDEDED" />
<TextView
android:id="@+id/tv_list_tile_native_ad_attribution_large"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:background="#F19938"
android:gravity="center"
android:text="Ad"
android:textColor="#FFFFFF"
android:visibility="invisible" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="80dp"
android:layout_marginLeft="80dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_list_tile_native_ad_headline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:textColor="#000000"
android:textSize="16sp"
tools:text="Headline" />
<TextView
android:id="@+id/tv_list_tile_native_ad_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:textColor="#828282"
android:textSize="14sp"
tools:text="body" />
</LinearLayout>
</FrameLayout>
</com.google.android.gms.ads.nativead.NativeAdView>
ListTileNativeAdFactory 클래스 만들기
- 프로젝트 창에서 com.codelab.flutter.admobinlineads 패키지를 마우스 오른쪽 버튼으로 클릭하고 New > Kotlin File/Class를 선택합니다.
ListTileNativeAdFactory
를 이름으로 입력하고 목록에서 Class를 선택합니다.
com.codelab.flutter.admobinlineads
패키지에ListTileNativeAdFactory
클래스가 생성되었음을 확인할 수 있습니다.- 다음과 같이
ListTileNativeAdFactory
클래스를 구현합니다. 이 클래스는GoogleMobileAdsPlugin.NativeAdFactory
인터페이스에서createNativeAd()
메서드를 구현합니다.
Factory 클래스는 네이티브 광고를 렌더링하기 위한 뷰 객체를 생성합니다. 코드에서 알 수 있듯이 Factory 클래스는 NativeAdView
를 생성하고 NativeAd
객체로 채웁니다.
ListTileNativeAdFactory.kt
// TODO: Implement ListTileNativeAdFactory class
package com.codelab.flutter.admobinlineads
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import com.google.android.gms.ads.nativead.NativeAd
import com.google.android.gms.ads.nativead.NativeAdView
import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin
class ListTileNativeAdFactory(val context: Context) : GoogleMobileAdsPlugin.NativeAdFactory {
override fun createNativeAd(
nativeAd: NativeAd,
customOptions: MutableMap<String, Any>?
): NativeAdView {
val nativeAdView = LayoutInflater.from(context)
.inflate(R.layout.list_tile_native_ad, null) as NativeAdView
with(nativeAdView) {
val attributionViewSmall =
findViewById<TextView>(R.id.tv_list_tile_native_ad_attribution_small)
val attributionViewLarge =
findViewById<TextView>(R.id.tv_list_tile_native_ad_attribution_large)
val iconView = findViewById<ImageView>(R.id.iv_list_tile_native_ad_icon)
val icon = nativeAd.icon
if (icon != null) {
attributionViewSmall.visibility = View.VISIBLE
attributionViewLarge.visibility = View.INVISIBLE
iconView.setImageDrawable(icon.drawable)
} else {
attributionViewSmall.visibility = View.INVISIBLE
attributionViewLarge.visibility = View.VISIBLE
}
this.iconView = iconView
val headlineView = findViewById<TextView>(R.id.tv_list_tile_native_ad_headline)
headlineView.text = nativeAd.headline
this.headlineView = headlineView
val bodyView = findViewById<TextView>(R.id.tv_list_tile_native_ad_body)
with(bodyView) {
text = nativeAd.body
visibility = if (nativeAd.body.isNotEmpty()) View.VISIBLE else View.INVISIBLE
}
this.bodyView = bodyView
setNativeAd(nativeAd)
}
return nativeAdView
}
}
ListTileNativeAdFactory 클래스 등록
NativeAdFactory
의 인스턴스를 Flutter 측에서 사용하려면 GoogleMobileAdsPlugin
에 등록해야 합니다.
MainActivity.kt
파일을 열고configureFlutterEngine()
메서드와cleanUpFlutterEngine()
메서드를 재정의합니다.configureFlutterEngine()
메서드에서 고유한 문자열 ID(listTile
)를 사용하여ListTileNativeAdFactory
클래스를 등록합니다.
MainActivity.kt
class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
// TODO: Register the ListTileNativeAdFactory
GoogleMobileAdsPlugin.registerNativeAdFactory(
flutterEngine, "listTile", ListTileNativeAdFactory(context))
}
...
}
- 정리 프로세스 중에 모든
NativeAdFactory
인스턴스를 등록 취소해야 합니다.cleanUpFlutterEngine()
메서드에서ListTileNativeAdFactory
클래스를 등록 취소합니다.
MainActivity.kt
class MainActivity: FlutterActivity() {
...
override fun cleanUpFlutterEngine(flutterEngine: FlutterEngine) {
super.cleanUpFlutterEngine(flutterEngine)
// TODO: Unregister the ListTileNativeAdFactory
GoogleMobileAdsPlugin.unregisterNativeAdFactory(flutterEngine, "listTile")
}
}
이제 ListTileNativeAdFactory
클래스를 사용하여 Android에서 네이티브 광고를 렌더링할 준비가 되었습니다.
iOS용 NativeAdFactory 구현(Objective-C)
ios/Podfile
파일 또는 iOS 폴더의 파일을 열고 Open iOS module in Xcode(Xcode에서 iOS 모듈 열기)를 클릭하여 iOS 프로젝트를 엽니다.
네이티브 광고 레이아웃 준비
네이티브 광고 애셋을 배치하려면 맞춤 뷰(*.xib
)가 있어야 합니다. 이 Codelab에서는 사전 구성된 뷰를 사용하여 노력을 최소화할 수 있습니다.
Xcode에서 iOS 프로젝트가 열리면 Runner(러너) 프로젝트에 ListTileNativeAdView.xib가 있는지 확인합니다.
ListTileNativeAdFactory 클래스 만들기
- 프로젝트 탐색기에서 Runner(러너) 그룹을 마우스 오른쪽 버튼으로 클릭하고 New File(새 파일)을 선택하여 새 클래스의 헤더 파일을 만듭니다.
- 템플릿 대화상자에서 Header File(헤더 파일)을 선택하고 이름을
ListTileNativeAdFactory
로 지정합니다. ListTileNativeAdFactory.h
파일이 생성되면 다음과 같이ListNativeAdFactory
클래스를 정의합니다.
ListTileNativeAdFactory.h
#ifndef ListTileNativeAdFactory_h
#define ListTileNativeAdFactory_h
// TODO: Import FLTGoogleMobileAdsPlugin.h
#import "FLTGoogleMobileAdsPlugin.h"
// TODO: Declare ListTileNativeAdFactory
@interface ListTileNativeAdFactory : NSObject<FLTNativeAdFactory>
@end
#endif /* ListTileNativeAdFactory_h */
- Runner(러너) 그룹에서 New File(새 파일)을 선택하여 Objective-C 파일을 만듭니다.
- 다음 대화상자의 File(파일) 필드에
ListTileNativeAdFactory
를 입력하고 파일 형식으로 Empty File(빈 파일)을 선택합니다.
- Next(다음)를 클릭하면 새 파일을 만들 폴더를 선택하라는 메시지가 표시됩니다. 아무 것도 변경하지 않고 Create(생성)를 클릭합니다.
- 다음과 같이
ListTileNativeFactory
클래스를 구현합니다. 이 클래스는FLTNativeAdFactory
프로토콜에서createNativeAd()
메서드를 구현합니다.
Factory 클래스는 네이티브 광고를 렌더링하기 위한 뷰 객체를 생성합니다. 코드에서 알 수 있듯이 Factory 클래스는 GADNativeAdView
를 생성하고 GADNativeAd
객체로 채웁니다.
ListTileNativeAdFactory.m
// TODO: Import ListTileNativeAdFactory.h
#import "ListTileNativeAdFactory.h"
// TODO: Implement ListTileNativeAdFactory
@implementation ListTileNativeAdFactory
- (GADNativeAdView *)createNativeAd:(GADNativeAd *)nativeAd
customOptions:(NSDictionary *)customOptions {
GADNativeAdView *nativeAdView =
[[NSBundle mainBundle] loadNibNamed:@"ListTileNativeAdView" owner:nil options:nil].firstObject;
((UILabel *)nativeAdView.headlineView).text = nativeAd.headline;
((UILabel *)nativeAdView.bodyView).text = nativeAd.body;
nativeAdView.bodyView.hidden = nativeAd.body ? NO : YES;
((UIImageView *)nativeAdView.iconView).image = nativeAd.icon.image;
nativeAdView.iconView.hidden = nativeAd.icon ? NO : YES;
nativeAdView.callToActionView.userInteractionEnabled = NO;
nativeAdView.nativeAd = nativeAd;
return nativeAdView;
}
@end
ListTileNativeAdFactory 클래스 등록
FLTNativeAdFactory
의 구현을 Flutter 측에서 사용하려면 FLTGoogleMobileAdsPlugin
에 등록해야 합니다.
AppDelegate.m
파일을 열고 [FLTGoogleMobileAdsPlugin registerNativeAdFactory]
메서드를 호출하여 ListTileNativeAdFactory
를 고유 문자열 ID(listTile
)로 등록합니다.
AppDelegate.m
#import "AppDelegate.h"
#import "GeneratedPluginRegistrant.h"
// TODO: Import ListTileNativeAdFactory.h
#import "ListTileNativeAdFactory.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
// TODO: Register ListTileNativeAdFactory
ListTileNativeAdFactory *listTileFactory = [[ListTileNativeAdFactory alloc] init];
[FLTGoogleMobileAdsPlugin registerNativeAdFactory:self
factoryId:@"listTile"
nativeAdFactory:listTileFactory];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
이제 ListTileNativeAdFactory
를 사용하여 iOS에서 네이티브 광고를 렌더링할 수 있습니다.
iOS용 NativeAdFactory 구현(Swift)
ios/Podfile
파일 또는 iOS 폴더의 파일을 열고 Open iOS module in Xcode(Xcode에서 iOS 모듈 열기)를 클릭하여 iOS 프로젝트를 엽니다.
네이티브 광고 레이아웃 준비
네이티브 광고 애셋을 배치하려면 맞춤 뷰(*.xib
)가 있어야 합니다. 이 Codelab에서는 사전 구성된 뷰를 사용하여 노력을 최소화할 수 있습니다.
Xcode에서 iOS 프로젝트가 열리면 Runner(러너) 프로젝트에 ListTileNativeAdView.xib가 있는지 확인합니다.
ListTileNativeAdFactory 클래스 만들기
- 프로젝트 탐색기에서 Runner(러너) 그룹을 마우스 오른쪽 버튼으로 클릭하고 New File(새 파일)을 선택하여 새 클래스의 헤더 파일을 만듭니다.
- 템플릿 대화상자에서 Swift File(Swift 파일)을 선택하고 이름을
ListTileNativeAdFactory
로 지정합니다. ListTileNativeAdFactory.swift
파일이 생성되면ListNativeAdFactory
클래스를 구현합니다.
이 클래스는 FLTNativeAdFactory
프로토콜에서 createNativeAd()
메서드를 구현합니다.
Factory 클래스는 네이티브 광고를 렌더링하기 위한 뷰 객체를 생성합니다. 코드에서 알 수 있듯이 Factory 클래스는 GADNativeAdView
를 생성하고 GADNativeAd
객체로 채웁니다.
ListTileNativeAdFactory.swift
// TODO: Import google_mobile_ads
import google_mobile_ads
// TODO: Implement ListTileNativeAdFactory
class ListTileNativeAdFactory : FLTNativeAdFactory {
func createNativeAd(_ nativeAd: GADNativeAd,
customOptions: [AnyHashable : Any]? = nil) -> GADNativeAdView? {
let nibView = Bundle.main.loadNibNamed("ListTileNativeAdView", owner: nil, options: nil)!.first
let nativeAdView = nibView as! GADNativeAdView
(nativeAdView.headlineView as! UILabel).text = nativeAd.headline
(nativeAdView.bodyView as! UILabel).text = nativeAd.body
nativeAdView.bodyView!.isHidden = nativeAd.body == nil
(nativeAdView.iconView as! UIImageView).image = nativeAd.icon?.image
nativeAdView.iconView!.isHidden = nativeAd.icon == nil
nativeAdView.callToActionView?.isUserInteractionEnabled = false
nativeAdView.nativeAd = nativeAd
return nativeAdView
}
}
ListTileNativeAdFactory 클래스 등록
FLTNativeAdFactory
의 구현을 Flutter 측에서 사용하려면 FLTGoogleMobileAdsPlugin
에 등록해야 합니다.
AppDelegate.m
파일을 열고 FLTGoogleMobileAdsPlugin.registerNativeAdFactory()
메서드를 호출하여 ListTileNativeAdFactory
를 고유 문자열 ID(listTile
)로 등록합니다.
AppDelegate.swift
import UIKit
import Flutter
// TODO: Import google_mobile_ads
import google_mobile_ads
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
// TODO: Register ListTileNativeAdFactory
let listTileFactory = ListTileNativeAdFactory()
FLTGoogleMobileAdsPlugin.registerNativeAdFactory(
self, factoryId: "listTile", nativeAdFactory: listTileFactory)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
이제 ListTileNativeAdFactory
를 사용하여 iOS에서 네이티브 광고를 렌더링할 수 있습니다.
Flutter 위젯과 네이티브 광고 통합
lib/native_inline_page.dart
파일을 엽니다. 다음 행을 추가하여ad_helper.dart
와google_mobile_ads.dart
를 가져옵니다.
native_inline_page.dart
...
// TODO: Import ad_helper.dart
import 'package:admob_inline_ads_in_flutter/ad_helper.dart';
// TODO: Import google_mobile_ads.dart
import 'package:google_mobile_ads/google_mobile_ads.dart';
class NativeInlinePage extends StatefulWidget {
...
}
_NativeInlinePageState
클래스에서 네이티브 광고에 다음 멤버와 메서드를 추가합니다.
_kAdIndex
는 배너 광고가 표시될 인덱스를 나타내며 _getDestinationItemIndex()
메서드에서 항목 인덱스를 계산하는 데 사용됩니다.
native_inline_page.dart
class _NativeInlinePageState extends State<NativeInlinePage> {
// TODO: Add _kAdIndex
static final _kAdIndex = 4;
// TODO: Add a native ad instance
NativeAd? _ad;
...
// TODO: Add _getDestinationItemIndex()
int _getDestinationItemIndex(int rawIndex) {
if (rawIndex >= _kAdIndex && _ad != null) {
return rawIndex - 1;
}
return rawIndex;
}
...
}
initState()
메서드에서ListTileNativeAdFactory
를 사용하여NativeAd
를 만들고 로드하여 네이티브 광고 뷰를 생성합니다.
플러그인에 Factory를 등록하는 데 사용된 것과 동일한 Factory ID(listTile
)가 사용됩니다.
native_inline_page.dart
@override
void initState() {
super.initState();
// TODO: Create a NativeAd instance
_ad = NativeAd(
adUnitId: AdHelper.nativeAdUnitId,
factoryId: 'listTile',
request: AdRequest(),
listener: NativeAdListener(
onAdLoaded: (ad) {
setState(() {
_ad = ad as NativeAd;
});
},
onAdFailedToLoad: (ad, error) {
// Releases an ad resource when it fails to load
ad.dispose();
print('Ad load failed (code=${error.code} message=${error.message})'); },
),
);
_ad.load();
}
- 가능한 경우 배너 광고를 표시하도록
build()
메서드를 수정합니다. itemCount,
를 업데이트하여 배너 광고 항목을 계산하고itemBuilder,
를 업데이트하여 광고가 로드되면 광고 인덱스(_kAdIndex
)에서 배너 광고를 렌더링합니다._getDestinationItemIndex()
메서드를 사용하여 콘텐츠 항목의 인덱스를 가져오도록 코드를 업데이트합니다.
native_inline_page.dart
@override
Widget build(BuildContext context) {
return Scaffold(
...
body: ListView.builder(
// TODO: Adjust itemCount based on the ad load state
itemCount: widget.entries.length + (_ad != null ? 1 : 0),
itemBuilder: (context, index) {
// TODO: Render a banner ad
if (_ad != null && index == _kAdIndex) {
return Container(
height: 72.0,
alignment: Alignment.center,
child: AdWidget(ad: _ad!),
);
} else {
// TODO: Get adjusted item index from _getDestinationItemIndex()
final item = widget.entries[_getDestinationItemIndex(index)];
return ListTile(
...
);
}
},
),
);
}
dispose()
콜백 메서드에서NativeAd.dispose()
메서드를 호출하여NativeAd
객체와 연결된 리소스를 해제합니다.
native_inline_page.dart
@override
void dispose() {
// TODO: Dispose a NativeAd object
_ad?.dispose();
super.dispose();
}
이제 완료됐습니다. 프로젝트를 실행하고 홈페이지에서 Native inline ad(네이티브 인라인 광고) 버튼을 클릭합니다. 광고가 로드되면 목록 중간에 네이티브 광고가 표시됩니다.
9. 완료
Codelab을 완료했습니다. 이 Codelab의 완성된 코드는 complete 또는 complete_kotlin_swift 폴더에서 찾을 수 있습니다.