Xamarin.Formsでカスタムレンダラーを使って、AdMobのバナー広告を表示する(iOS/Android)


概要

Xamarin.Formsで、AdMobのバナー広告を表示してみます。
ここではカスタムレンダラーを使って、iOSとAndroidに表示してみます。(`・ω・´)
下記のサンプルをベースに説明します。

サンプル

GitHubに置いておきました。
AddAdMobBannerSample

こんな感じで、バナー広告が表示されます。(実機でも表示できました(∩´∀`)∩)

制作環境 (動作確認環境)

  • macOS Sierra 10.2
  • Xamarin Studio 6.1.1(Build15)
    • Xamarin.iOS 10.0.1.10
    • Xamarin.Android 7.0.1.3

流れ

  1. AdMobの広告ユニットIDの取得
  2. PCL(共通プロジェクト)での作業
  3. iOSプロジェクトでの作業
  4. Androidプロジェクトでの作業

1. AdMobの広告ユニットIDの取得

詳細は割愛しますが、AdMobの広告ユニットIDをiOS用とAndroid用の2つ用意してください。
※iOSでは、下記にチェックを入れておいてください。
広告リクエストの HTTPS 対応 アプリからの広告リクエストのセキュリティを高める

2. PCL(共通プロジェクト)での作業

ここでは、カスタム元のビューを作成したり、UI(Xaml)に広告を追加したりします。

AdMobBanner.cs

中身が空で心配になりますが、これで大丈夫です。

using System;
using Xamarin.Forms;

namespace AddAdMobBannerSample
{
    public class AdMobBanner : ContentView
    {
        public AdMobBanner()
        {
        }
    }
}

MainPage.xaml

AdMobのバナーサイズが320x50なので、このサイズが収まるようにしてください。
(marginやpaddingで表示領域が狭くなってしまったりしても、広告が表示されなくなります。)

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             xmlns:controls="clr-namespace:AddAdMobBannerSample;assembly=AddAdMobBannerSample" 
             x:Class="AddAdMobBannerSample.MainPage">
    <ContentPage.Content>
        <StackLayout VerticalOptions="Center" HorizontalOptions="Center">
            <controls:AdMobBanner WidthRequest="320" HeightRequest="50" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

3. iOSプロジェクトでの作業

iOS用のパッケージを追加したり、カスタムレンダラーを作成したりします。

パッケージ追加

下記のパッケージを追加してください。
「 Xamarin.Google.iOS.MobileAds 」

AdMobBannerRenderer.cs

iOS用のカスタムレンダラーです。
ここにiOS用の広告ユニットIDを記載してください。

using System;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using Google.MobileAds;
using UIKit;
using CoreGraphics;
using AddAdMobBannerSample;
using AddAdMobBannerSample.iOS.Renderers;

[assembly: ExportRenderer(typeof(AdMobBanner), typeof(AdMobBannerRenderer))]
namespace AddAdMobBannerSample.iOS.Renderers
{
    public class AdMobBannerRenderer : ViewRenderer
    {
        const string adUnitID = "Insert Your AdUnitID(for iOS)";

        BannerView adMobBanner;
        bool viewOnScreen;

        protected override void OnElementChanged(ElementChangedEventArgs<View> e)
        {
            base.OnElementChanged(e);

            if (e.NewElement == null)
                return;

            if (e.OldElement == null)
            {
                adMobBanner = new BannerView(AdSizeCons.Banner, new CGPoint(-10, 0))
                {
                    AdUnitID = adUnitID,
                    RootViewController = UIApplication.SharedApplication.Windows[0].RootViewController
                };
                adMobBanner.AdReceived += (sender, args) =>
                {
                    if (!viewOnScreen) AddSubview(adMobBanner);
                    viewOnScreen = true;
                };
                adMobBanner.LoadRequest(Request.GetDefaultRequest());
                SetNativeControl(adMobBanner);
            }
        }
    }
}

AppDelegate.cs

[Export("window")]以下を追加します。
これを追加しないとアプリの起動時にクラッシュしてしまいます。
参考

using System;
using System.Collections.Generic;
using System.Linq;

using Foundation;
using UIKit;

namespace AddAdMobBannerSample.iOS
{
    [Register("AppDelegate")]
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    {
        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();

            LoadApplication(new App());

            return base.FinishedLaunching(app, options);
        }

        [Export("window")]
        public UIWindow GetWindow()
        {
            return UIApplication.SharedApplication.Windows[0];
        }
    }
}

4. Androidプロジェクトでの作業

Android用のパッケージを追加したり、カスタムレンダラーを作成したりします。

パッケージ追加

下記のパッケージを追加してください。
「 Xamarin.GooglePlayServices.Ads 」
「 Xamarin.GooglePlayServices.Basement 」(.Adsを入れると自動で入ります)

AdMobBannerRenderer.cs

Android用のカスタムレンダラーです。
ここにAndroid用の広告ユニットIDを記載してください。

using AddAdMobBannerSample;
using AddAdMobBannerSample.Droid.Renderers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(AdMobBanner), typeof(AdMobBannerRenderer))]
namespace AddAdMobBannerSample.Droid.Renderers
{
    public class AdMobBannerRenderer:ViewRenderer<AdMobBanner, Android.Gms.Ads.AdView>
    {
        protected override void OnElementChanged(ElementChangedEventArgs<AdMobBanner> e)
        {
            const string adUnitID = "Insert Your AdUnitID(for Android)";

            base.OnElementChanged(e);

            if (Control == null)
            {
                var adMobBanner = new Android.Gms.Ads.AdView(Forms.Context);
                adMobBanner.AdSize = Android.Gms.Ads.AdSize.Banner;
                adMobBanner.AdUnitId = adUnitID;

                var requestbuilder = new Android.Gms.Ads.AdRequest.Builder();
                adMobBanner.LoadAd(requestbuilder.Build());

                SetNativeControl(adMobBanner);
            }
        }
    }
}

AndroidManifest.xml

INTERNETとACCESS_NETWORK_STATEのパーミッションが必要なので追加します。
また、<activity android:name="com.google.android.gms.ads.AdActivity" から始まる一行も必須です。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="jp.co.noraneko.addadmobbannersample">
    <uses-sdk android:minSdkVersion="15" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <application android:label="AddAdMobBannerSample">
        <activity android:name="com.google.android.gms.ads.AdActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" android:theme="@android:style/Theme.Translucent" />
    </application>
</manifest>

おわりに

これで、Xamarin.Formsで作ったアプリにAdMobのバナー広告を表示することができました(∩´∀`)∩
カスタムレンダラーといってもそこまで複雑なものでもないので、
気軽に広告を入れることができるかなーと思います。