Flutter Google Admob 배너광고 넣기(+android 튕김에러 대처)

악어·2024년 2월 2일
2

Flutter 개발

목록 보기
4/8
post-thumbnail

플러터 앱에 광고를 넣어보자

카페자리에 배너 광고를 시범 도입하기로했다.
어려운 기능은 아니었지만, 꼭 짚어야 할 부분이
있어 포스팅으로 정리해보려한다.



순서

전체적인 흐름은 다음과 같다.

1. Admob에서 계정 등록 > 앱 등록 > 광고단위 등록

2. Android / iOS 환경설정

3. (선택) Flutter beta channel 업그레이드

4. google_mobile_ads 설치

5. 기능구현



진행

1. Admob 계정등록 > 앱등록 > 광고단위등록

애드몹 홈페이지에 들어가면 물 흐르듯
자연스럽게 할 수 있을 것이다.


  • 앱 등록된 모습

  • 광고단위(배너) 등록된 모습


한 가지 팁은 firebase에 project를 등록해
google analytics를 사용하고 있는 경우,

앱 > 앱설정 > 연결된 서비스 관리하기

로 이동해 firebase project와 연동하는 것이다.



2. Android / iOS 환경설정

안드로이드는 여기,
iOS는 여기
자세한 설명이 나와있다.

다만 우리는 플러터로 진행할 예정이니,
안드로이드의 경우에는 AndroidManifest.xml 설정까지,
iOS의 경우에는 Info.plist 설정까지만 진행하고
sdk추가는 하지 않도록 하자.



3. (선택) Flutter beta channel 업그레이드

이 부분이 사실 이 포스트를 쓰게된 이유이다.
지금까지 나는 flutter 3.16 버전을 쓰고 있었는데,
이상하게 안드로이드에서 배너광고를 넣을 경우
앱이 튕기는 에러가 발생했다.

버그에 일관성이 없어서 재현도 어렵고
원인도 찾기 어려운 버그였다.
에러 로그로 구글링해본 결과 가장
비슷한 현상은 이 블로그 포스팅과 같았다.

해결 방법은 그냥 flutter를 beta버전으로
업그레이드 하는것이다..
(beta버전이 내키지 않다면 downgrade도 방법이다)

// 터미널에서 실행
$ flutter channel beta
$ flutter upgrade


4. google_mobile_ads 설치

애드몹 사용을 도와주는 패키지는
google_mobile_ads라는 친구이다.
여기에서 버전을 확인하고 설치해주자.

../root/pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
    .
    .
    # google ad
    google_mobile_ads: ^4.0.0
    .
    .

이후 터미널에서 flutter pub get 실행 또는
IDE에서 pub get을 실행해준다.



5. 기능구현

여기까지 잘 왔다면 코드 자체는 어렵지 않다.
여러가지 구현 방법이 있겠으나,

나는 AdManager class를 만들고
모든 banner ad들을
Singleton으로 관리해보았다.

먼저 ad_manager.dart 파일을
아래와같이 작성해주자.

import 'dart:io';
import 'package:google_mobile_ads/google_mobile_ads.dart';


class AdManager {
  // singleton instance
  static AdManager instance = AdManager();
  
  // 스크린 별로 사용될 AdManagerBannerAd 객체들
  AdManagerBannerAd? myCafeScreenBannerAd;
  AdManagerBannerAd? challengeScreenBannerAd;
  AdManagerBannerAd? myPageScreenBannerAd;
  AdManagerBannerAd? shopScreenBannerAd;
  AdManagerBannerAd? notificationScreenBannerAd;
  AdManagerBannerAd? bottomFullSheetBannerAd;
  
  AdManager({
    this.myCafeScreenBannerAd,
    this.challengeScreenBannerAd,
    this.myPageScreenBannerAd,
    this.shopScreenBannerAd,
    this.notificationScreenBannerAd,
    this.bottomFullSheetBannerAd
  });
  
  // AdManager 객체 초기화
  factory AdManager.init() => instance = AdManager(
    myCafeScreenBannerAd: _loadBannerAd(),
    challengeScreenBannerAd: _loadBannerAd(),
    myPageScreenBannerAd: _loadBannerAd(),
    shopScreenBannerAd: _loadBannerAd(),
    notificationScreenBannerAd: _loadBannerAd(),
    bottomFullSheetBannerAd: _loadBannerAd(),
  );
}



// AdManagerBannerAd 객체를 로드하는 함수
AdManagerBannerAd _loadBannerAd() {
  const String androidBannerAdUnitId = '/6499/example/banner';
  const String iosBannerAdUnitId = '/6499/example/banner';

  String adUnitId = androidBannerAdUnitId;
  if(Platform.isIOS) adUnitId = iosBannerAdUnitId;

  return AdManagerBannerAd(
    adUnitId: adUnitId,
    request: const AdManagerAdRequest(),
    sizes: [AdSize.banner],
    listener: AdManagerBannerAdListener(),
  )..load();
}

얼핏 봤을 때 복잡해 보일 수 있지만,
뜯어보면 배너광고가 들어갈 자리가 6개라
같은 로직을 여러번 써놓았을 뿐이다.


init을 통해 6개 스크린에 들어갈
banner ad들을 모두 로드하며
Singleton instance를 만든다.

_loadBannerAd 함수를 보면,
target 기기에 따라 다른
adUnitId를 적용하는 것을 볼 수 있다.

카페자리는 안드로이드 / iOS 두 가지 기종만
서비스하므로 위와같이 두 가지 케이스만
고려했는데, 다른 기기까지 타겟팅 한다면
이부분을 적당히 고쳐 쓰면 된다.


위 androidBannerAdUnitId와 iosBannerAdUnitId는
테스트용 광고단위 id이다.
실제 서비스할때는 1번에서 만든
광고단위의 id를 가져다 넣으면 된다.


마지막으로 재사용 가능한 Widget을 만들어주자.
AdManagerBannerAd객체를 파라미터로 받고,
기기의 가로사이즈를 전부 채우는
배너 광고 위젯을 만들 것이다.

full_width_banner_ad.dart 파일을
아래와 같이 작성해주자.

import 'package:flutter/widgets.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';


class FullWidthBannerAd extends StatelessWidget {
  final AdManagerBannerAd? bannerAd;
  final double sidePadding;
  
  const FullWidthBannerAd({
    super.key, 
    required this.bannerAd, 
    this.sidePadding = 0
  });

  @override
  Widget build(BuildContext context) {
    if(bannerAd != none) {
      return SizedBox(
        width: MediaQuery.of(context).size.width - sidePadding * 2,
        height: bannerAd!.sizes.first.height.toDouble(),
        child: AdWidget(ad: bannerAd!)
      );
    } else {
      return const SizedBox(width: 0, height: 0);
    }
  }
}

파라미터로 받은 AdManagerBannerAd가 null값이면
크기가 0인 SizedBox를 return할 것이다.

또, 기본적으로 기기의 width를 배너의 width로 하되
sidePadding값을 입력해줄 경우 padding값만큼
width길이를 줄일 수 있도록 했다.


이제 준비는 끝났다.
바로 사용해보자.

../root/main.dart

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';


void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  .
  .
  // 광고 init
  AdManager.init();
  .
  .
}

main에서 위처럼 AdManager instance를 init해준다.
이후에는 사용하고 싶은 곳으로 가서
다음과 같이 사용하면 된다.

@override
Widget build(BuildContext context) {
  return Column(
    children: [
      .
      .
      // 패딩 적용
      FullWidthBannerAd(
        bannerAd: AdManager.instance.myCafeScreenBannerAd,
        sidePadding: 10.0
       ),
      .
      .
    ]
  );
}
@override
Widget build(BuildContext context) {
  return Column(
    children: [
      .
      .
      // 패딩x (배너width = deviceWidth)
      FullWidthBannerAd(bannerAd: AdManager.instance.shopScreenBannerAd),
      .
      .
    ]
  );
}


완성!!!

profile
냅다 회사부터 세워버린 개발자

7개의 댓글

comment-user-thumbnail
2024년 4월 9일

안녕하세요 개발자님 혹시 실례가 안된다면 포인트샵 기능은 어떻게 구현하신건지 여쭈어봐도 될까요..? 혹시 기프티쇼 비즈 api를 받으신걸까요?

3개의 답글

관련 채용 정보