프레임워크/Flutter

[flutter] Google AdMob Native Ads 적용하기-플랫폼별 설정(Android편)

연어바케트 2025. 1. 16. 20:48
반응형
  • 네이티브 템플릿: Dart API로 스타일이 지정된 사전 정의된 네이티브 템플릿입니다.
  • 플랫폼 설정: Android 및 iOS 레이아웃 도구를 사용하여 정의된 맞춤 플랫폼별 레이아웃입니다

1. settings.gradle 설정 

def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
    pluginsFile.withInputStream { stream -> plugins.load(stream) }
}

plugins.each { name, path ->
    def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
    include ":$name"
    project(":$name").projectDir = pluginDirectory
}

 

2. native_ad.xml 설정 

native에서 보여질 화면이 xml 형식으로 봐어 있어 이를 앱 디자인에 맞게 표현할 수 있도록 할 디자인을 설정한다. 

아래 코드는 공식문서에서 제공하는 기본 코드이다.  

android -> app -> src -> main -> res -> layout 에 아래 코드를 위치 시켰다.

<com.google.android.gms.ads.nativead.NativeAdView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_gravity="center"
      android:background="#FFFFFF"
      android:minHeight="50dp"
      android:orientation="vertical">
    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:paddingLeft="20dp"
        android:paddingRight="20dp"
        android:paddingTop="3dp">

      <LinearLayout
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:orientation="horizontal">

        <ImageView
            android:id="@+id/ad_app_icon"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:adjustViewBounds="true"
            android:paddingBottom="5dp"
            android:paddingEnd="5dp"
            android:paddingRight="5dp"/>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

          <TextView
              android:id="@+id/ad_headline"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:textColor="#0000FF"
              android:textSize="16sp"
              android:textStyle="bold" />

          <LinearLayout
              android:layout_width="match_parent"
              android:layout_height="wrap_content">

            <TextView
                android:id="@+id/ad_advertiser"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:gravity="bottom"
                android:textSize="14sp"
                android:textStyle="bold"/>

            <RatingBar
                android:id="@+id/ad_stars"
                style="?android:attr/ratingBarStyleSmall"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:isIndicator="true"
                android:numStars="5"
                android:stepSize="0.5" />
          </LinearLayout>

        </LinearLayout>
      </LinearLayout>

      <LinearLayout
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:orientation="vertical">

        <TextView
            android:id="@+id/ad_body"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="20dp"
            android:layout_marginEnd="20dp"
            android:textSize="12sp" />

        <com.google.android.gms.ads.nativead.MediaView
            android:id="@+id/ad_media"
            android:layout_gravity="center_horizontal"
            android:layout_width="250dp"
            android:layout_height="175dp"
            android:layout_marginTop="5dp" />

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="end"
            android:orientation="horizontal"
            android:paddingBottom="10dp"
            android:paddingTop="10dp">

          <TextView
              android:id="@+id/ad_price"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:paddingLeft="5dp"
              android:paddingStart="5dp"
              android:paddingRight="5dp"
              android:paddingEnd="5dp"
              android:textSize="12sp" />

          <TextView
              android:id="@+id/ad_store"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:paddingLeft="5dp"
              android:paddingStart="5dp"
              android:paddingRight="5dp"
              android:paddingEnd="5dp"
              android:textSize="12sp" />

          <Button
              android:id="@+id/ad_call_to_action"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:gravity="center"
              android:textSize="12sp" />
        </LinearLayout>
      </LinearLayout>
    </LinearLayout>
  </LinearLayout>
</com.google.android.gms.ads.nativead.NativeAdView>

 

3. NativeAdFactory 구현

공식 문서 예제 코드를 바탕으로 코틀린으로 NativeAdFactory를 구현하였다. 
NativeAdFactory.kt는 MainActivity.kt와 같은 패키지에 위치 시켰다. 

class SawangNativeAdFactory(private val layoutInflater: LayoutInflater) : NativeAdFactory {

    override fun createNativeAd(nativeAd: NativeAd, customOptions: Map<String, Any>?): NativeAdView {
        val adView = layoutInflater.inflate(R.layout.native_ad_layout, null) as NativeAdView

        //XML레이아웃에서 정의한 각UI요소를 adView에 연결
        adView.mediaView = adView.findViewById(R.id.ad_media)
        adView.headlineView = adView.findViewById(R.id.ad_headline)
        adView.bodyView = adView.findViewById(R.id.ad_body)
        adView.callToActionView = adView.findViewById(R.id.ad_call_to_action)
        adView.iconView = adView.findViewById(R.id.ad_app_icon)
        adView.priceView = adView.findViewById(R.id.ad_price)
        adView.starRatingView = adView.findViewById(R.id.ad_stars)
        adView.storeView = adView.findViewById(R.id.ad_store)
        adView.advertiserView = adView.findViewById(R.id.ad_advertiser)

        //광고 데이터를 연결된 UI요소에 설정 
        (adView.headlineView as TextView).text = nativeAd.headline
        adView.mediaView?.mediaContent = nativeAd.mediaContent

        if (nativeAd.body == null) {
            adView.bodyView?.visibility = View.INVISIBLE
        } else {
            adView.bodyView?.visibility = View.VISIBLE
            (adView.bodyView as TextView).text = nativeAd.body
        }

        if (nativeAd.callToAction == null) {
            adView.callToActionView?.visibility = View.INVISIBLE
        } else {
            adView.callToActionView?.visibility = View.VISIBLE
            (adView.callToActionView as Button).text = nativeAd.callToAction
        }

        if (nativeAd.icon == null) {
            adView.iconView?.visibility = View.GONE
        } else {
            (adView.iconView as ImageView).setImageDrawable(nativeAd.icon?.drawable)
            adView.iconView?.visibility = View.VISIBLE
        }

        if (nativeAd.price == null) {
            adView.priceView?.visibility = View.INVISIBLE
        } else {
            adView.priceView?.visibility = View.VISIBLE
            (adView.priceView as TextView).text = nativeAd.price
        }

        if (nativeAd.store == null) {
            adView.storeView?.visibility = View.INVISIBLE
        } else {
            adView.storeView?.visibility = View.VISIBLE
            (adView.storeView as TextView).text = nativeAd.store
        }

        if (nativeAd.starRating == null) {
            adView.starRatingView?.visibility = View.INVISIBLE
        } else {
            (adView.starRatingView as RatingBar).rating = nativeAd.starRating?.toFloat() ?: 0f
            adView.starRatingView?.visibility = View.VISIBLE
        }

        if (nativeAd.advertiser == null) {
            adView.advertiserView?.visibility = View.INVISIBLE
        } else {
            adView.advertiserView?.visibility = View.VISIBLE
            (adView.advertiserView as TextView).text = nativeAd.advertiser
        }
        
        //adView에 nativeAd 연결
        adView.setNativeAd(nativeAd)
        return adView
    }
}

 

4. NativeAdFactory 등록 

이제 Main Activity에 NativeAdFactory를 호출 할 수 있는 factoryId를 등록해야한다. 등록되어야 Flutter 코드에서 factoryId로 인스터스화하여 사용할 수 있다. String 식별자를 사용하여 등록하면 된다. 아래는 코틀린 코드로 제작되었다. 

class MainActivity : FlutterFragmentActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        GoogleMobileAdsPlugin.registerNativeAdFactory(
            flutterEngine,
            "NativeAdFactory",
            NativeAdFactory(layoutInflater)
        )
    }

    override fun cleanUpFlutterEngine(flutterEngine: FlutterEngine) {
        super.cleanUpFlutterEngine(flutterEngine)
        GoogleMobileAdsPlugin.unregisterNativeAdFactory(flutterEngine, "NativeAdFactory")

    }
}

 

 

5. AdMobController 


 필자는 Getx를 사용하고 있어 Getx 형식으로 AdmobController을 만들어 주었다. 

class AdMobController extends GetxController {
  NativeAd? nativeAd;
  bool isAdLoaded = false;

  @override
  void onInit() {
    super.onInit();
    loadNativeAd();
  }

  void loadNativeAd() {
    nativeAd = NativeAd(
      adUnitId: 'ca-app-pub-3940256099942544/2247696110',
      factoryId: 'sawangNativeAdFactory',
      listener: NativeAdListener(
        onAdLoaded: (ad) {
          isAdLoaded = true;
        },
        onAdFailedToLoad: (ad, error) {
          ad.dispose();
          if (kDebugMode) {
            print(error);
          }
        },
      ),
      request: AdRequest(),
    )..load();
  }

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

 

 

6. AdWidget
AdMobController을 호출하여 광고를 띄워줄 위젯을 아래와 같이 만들었다. 

class AdmobNativeWidget extends GetWidget<AdMobController> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: controller.isAdLoaded
          ? SizedBox(
              width: 500,
              height: 500,
              child: AdWidget(ad: controller.nativeAd!),
            )
          : Container(),
    );
  }
}

 

6. 결과화면 

무척 잘 나오는것을 볼 수 있다. 

 

이제 XML을 수정해서 앱 디자인에 맞게 수정을 진행하면 끝!

반응형