유저 친화적 UI 와 수익 극대화를 위해 native ads 사용은 필수
코틀린으로 광고인스턴스를 불러온 후 xml 을 통해 화면에 보여주는 방식

해당 코드는 Google 이 제공하는 Cookbook 에서 발췌한 코드입니다.

 


MainActivity.kt

package com.danswer.youtubeseed

import android.view.LayoutInflater
import android.view.View
import android.widget.Button
import android.widget.ImageView
import android.widget.RatingBar
import android.widget.TextView
import com.google.android.gms.ads.nativead.NativeAd
import com.google.android.gms.ads.nativead.NativeAdView
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin
import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin.NativeAdFactory


class MainActivity: FlutterActivity() {
  override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
    flutterEngine.plugins.add(GoogleMobileAdsPlugin())
    super.configureFlutterEngine(flutterEngine)
    GoogleMobileAdsPlugin.registerNativeAdFactory(
        flutterEngine,
        "adFactoryExample",
        NativeAdFactoryExample(layoutInflater))
  }

  override fun cleanUpFlutterEngine(flutterEngine: FlutterEngine) {
    GoogleMobileAdsPlugin.unregisterNativeAdFactory(flutterEngine, "adFactoryExample")
  }
}

class NativeAdFactoryExample: NativeAdFactory {
  private var layoutInflater: LayoutInflater

  constructor(layoutInflater: LayoutInflater) {
    this.layoutInflater = layoutInflater
  }

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

    // Set the media view.
    adView.mediaView = adView.findViewById(R.id.ad_media)

    // Set other ad assets.
    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)
    
    // The headline and mediaContent are guaranteed to be in every NativeAd.
    (adView.headlineView as TextView).text = nativeAd?.headline
    adView.mediaView?.mediaContent = nativeAd?.mediaContent

    // These assets aren't guaranteed to be in every NativeAd, so it's important to
    // check before trying to display them.
    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()
      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
    }

    // This method tells the Google Mobile Ads SDK that you have finished populating your
    // native ad view with this native ad.
    if (nativeAd != null) {
      adView.setNativeAd(nativeAd)
    }

    return adView
  }
}


class TextNativeAdFactoryExample: NativeAdFactory {
  private var layoutInflater: LayoutInflater

  constructor(layoutInflater: LayoutInflater) {
    this.layoutInflater = layoutInflater
  }

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

    // Set the media view.
    adView.mediaView = adView.findViewById(R.id.ad_media)

    // Set other ad assets.
    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)
    
    // The headline and mediaContent are guaranteed to be in every NativeAd.
    (adView.headlineView as TextView).text = nativeAd?.headline
    adView.mediaView?.mediaContent = nativeAd?.mediaContent

    // These assets aren't guaranteed to be in every NativeAd, so it's important to
    // check before trying to display them.
    //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()
    //  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
    //}

    //// This method tells the Google Mobile Ads SDK that you have finished populating your
    //// native ad view with this native ad.
    //if (nativeAd != null) {
    //  adView.setNativeAd(nativeAd)
    //}

    return adView
  }
}

 

 

my_native_ad.xml

<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>

 

native_screen.dart

/// A simple app that loads a native ad.
import 'dart:io';

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

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

  @override
  NativeExampleState createState() => NativeExampleState();
}

class NativeExampleState extends State<NativeExample> {
  NativeAd? _nativeAd;
  bool _nativeAdIsLoaded = false;
  String? _versionString;

  final String _adUnitId = Platform.isAndroid
      ? '0F2CC08EBA730F1D6554F3D77EC120AF'
      : 'ca-app-pub-3940256099942544/3986624511';

  @override
  void initState() {
    super.initState();
    _loadAd();
    _loadVersionString();
  }

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Native Example',
        home: Scaffold(
            appBar: AppBar(
              title: const Text('Native Example'),
            ),
            body: Center(
              child: Column(
                children: [
                  Stack(children: [
                    SizedBox(
                        height: 300, width: MediaQuery.of(context).size.width),
                    if (_nativeAdIsLoaded && _nativeAd != null)
                      SizedBox(
                          height: 300,
                          width: MediaQuery.of(context).size.width,
                          child: AdWidget(ad: _nativeAd!))
                  ]),
                  TextButton(
                      onPressed: _loadAd, child: const Text("Refresh Ad")),
                  // if (_versionString != null) Text(_versionString!)
                  if (_versionString != null) Text(_versionString!)
                ],
              ),
            )));
  }

  /// Loads a native ad.
  void _loadAd() {
    setState(() {
      _nativeAdIsLoaded = false;
    });

    _nativeAd = NativeAd(
      adUnitId: 'ca-app-pub-3940256099942544/2247696110',
      factoryId: 'adFactoryExample',
      listener: NativeAdListener(
        onAdLoaded: (ad) {
          // ignore: avoid_print
          print('$NativeAd loaded.');
          setState(() {
            _nativeAdIsLoaded = true;
            // ad = ad as NativeAd;
          });
        },
        onAdFailedToLoad: (ad, error) {
          // ignore: avoid_print
          print('$NativeAd failedToLoad: $error');
          ad.dispose();
        },
        onAdClicked: (ad) {},
        onAdImpression: (ad) {},
        onAdClosed: (ad) {},
        onAdOpened: (ad) {},
        onAdWillDismissScreen: (ad) {},
        onPaidEvent: (ad, valueMicros, precision, currencyCode) {},
      ),
      request: const AdRequest(),
    )..load();
  }

  void _loadVersionString() {
    MobileAds.instance.getVersionString().then((value) {
      setState(() {
        _versionString = value;
      });
    });
  }
}

'개발 수익화 > 애드몹' 카테고리의 다른 글

모바일 앱 광고 참고자료(링크모음)  (0) 2023.08.25
Admob 광고 비싼 키워드 Top20  (0) 2023.08.25

https://www.igaworksblog.com/post/insight-%EC%83%9D%EC%A1%B4%EC%9D%84-%EC%9C%84%ED%95%B4-%EA%B0%84%EC%A0%88%ED%9E%88-%EB%B0%94%EB%9D%BC%EB%B4%A4%EB%8D%98-%EB%AA%A8%EB%B0%94%EC%9D%BC-%EC%95%B1-%EA%B4%91%EA%B3%A0-%EC%88%98%EC%9D%B5%ED%99%94%EC%9D%98-%EB%AA%A8%EB%93%A0-%EA%B2%83

'개발 수익화 > 애드몹' 카테고리의 다른 글

Flutter admob native tutorial(코틀린)  (0) 2023.12.11
Admob 광고 비싼 키워드 Top20  (0) 2023.08.25

Flutter 앱 개발 중 admob 을 통한 수익을 극대화 하기위해,

admob request 중 키워드를 설정 할 수 있다는 사실을 알게되었다.

 

키워드는 2개까지 설정할 수 있다고 Admob manual 에서 본듯?

(https://support.google.com/google-ads/answer/2453981?hl=en)

 

구현/확인해보니 설정한대로 되지 않아 검색도중 발견하여,

메모 삼아 포스팅합니다.

 

2011년 기준이란다 ㅎㅎ

 

 

아래는 2022년 비싼 키워드 관련 링크입니다.

https://www.wordstream.com/blog/ws/2017/06/27/most-expensive-keywords

 

The 25 Most Expensive Keywords in Google Ads

We’ve completed a new, comprehensive analysis of keyword data for five different currencies in English-speaking countries. We determined the top 25 most expensive keywords (meaning these niche markets are super-competitive) along with their average CPC.

www.wordstream.com

 

한국에서는 어쩔지 모르겠다 ㅎ

+ Recent posts