iPhoneアプリにiAdとAdmobを貼る

iPhoneアプリの収益化の方法はいくつかありますが、個人で作ってるアプリであれば広告を表示するのが手軽な方法だと思います。

本エントリではiAd広告とAdmob広告をハイブリッドに利用する方法を紹介します。他にも結構似たエントリはあるので、自分はこのハイブリッド広告を自作のクラスを使って手軽に貼り付ける方法を紹介します。

開発環境はXcodeが4.5.2、ARCをONにしています。

そもそも何故ハイブリッドにするのか

広告を一つだけにしてしまうとその広告が配信されていない状態が発生してしまいます。そういった無駄を無くすためにいくつかのアプリ内広告を貼り付けて可能な限り広告が表示されている状態にしたいと考えました。

本来ならiAd、Admob以外のアプリ内広告も利用すべきでしょうが今回は見送りました。AdStir( http://ja.ad-stir.com/ )なども今後使ってみたいです。

iAdを利用する

iAdはAppleが提供するアプリ内広告サービスです。 https://developer.apple.com/jp/iad/ iPhoneアプリに導入する広告としては真っ先に思い浮かぶものかなと思います。

実際にiAdに申し込むには結構面倒なのですがそちらは今回省略しています。 (備忘録として書いておけば良かったですが、他にも結構見つかるのでそちらを見てください...)

iAdの利用は標準で用意されている iAd.framework を利用します。

f:id:hayaishi:20121225202855p:plain

iAdを利用するには ADBannerViewDelegate の bannerView:didFailToReceiveAdWithError: (エラー処理)を実装している必要があります。

iAdSample.h

#import <iAd/iAd.h>
....
@interface AdSampleViewController : UIViewController <ADBannerViewDelegate> {
....
}

iAdSample.m

- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError * )error{
    // 広告失敗時の処理を書く
    banner.hidden = YES;
} 

このdelegateメソッドを実装したら後は適当にaddSubviewすれば表示されるようです。

...
self_iAd = [[ADBannerView alloc] initWithAdType:ADAdTypeBanner];
self._iAd.delegate = self;
[self.view addSubview:self._iAd];

実際にはADBannerViewDelegateのdelegateメソッドはもっとあって、 広告の読み込み成功時、広告がタップされた後、広告から戻ってきた時に呼び出されるものがあります。

Admobを利用する

AdmobはGoogleが提供するアプリ内広告です。iPhone以外にAndroidなどでも使えるのが良いですね。 単価についてなど、他の選択肢と比べてどうかはちゃんと調べて無いのですが、間を埋める用なので良いかなと思ってます。 https://jp.admob.com/

Admobは申し込んだらすぐに利用できるようになりました。 こちらは標準のframework以外に、Admobを使うためのSDKをダウンロードする必要があります。

ダウンロードしたSDKを解凍したら、その中にある、ヘッダファイルと.aファイルを自分のプロジェクト以下に移します。 Add-onsディレクトリは今回利用しなかったのでコピーしていません。

その他、必要なframeworkなどは以下のドキュメントを参考に設定しました。

また、忘れてはいけないのが

"4. You now need to add -ObjC to the Other Linker Flags of your application target's build setting:"

こちらで紹介されている通り、build settingOther Linker Flags-ObjC フラグを設定する必要があります。 これを忘れるとエラーになるので注意が必要です。 あとは、Introduction通りにコードを書けば表示することができます

  • GADBannerView.h をインポートする
  • アプリの UIViewController で GADBannerView インスタンスを宣言する
  • インスタンスを作成する
  • 広告のユニット ID(AdMob パブリッシャー ID)を設定する
  • ルート ビュー コントローラを設定する
  • ビューを UI に追加する
  • 広告と一緒にビューを読み込む

AdmobSample.h

#import "GADBannerView.h"
....
@interface AdSampleViewController : UIViewController  {
....
}

AdmobSample.m

// XXXXXXXX の部分を 取得したPublisher IDに置き換える
#define MY_BANNER_UNIT_ID   @"XXXXXXXXXXXXXXXXXX"
...
- (void)viewDidLoad
{
    [super viewDidLoad];
    self._admob = [[GADBannerView alloc]
        initWithFrame:CGRectMake(
            0.0,
            0.0,
            GAD_SIZE_320x50.width,
            GAD_SIZE_320x50.height
        )];
    self._admob.adUnitID = MY_BANNER_UNIT_ID;
    self._admob.delegate = self;
    self._admob.rootViewController = self;
    [self.view addSubview:self._admob];

    // 広告をリクエストする
    GADRequest *rq = [GADRequest request];
    [self._admob loadRequest:rq];
}

これで、広告がロードされればAdmobが表示されます。 Admobの読み込み失敗などは GADBannerViewDelegate の delegateメソッドによってハンドリングできます。

複数広告を貼ると結構面倒な処理が増える

まあ、しょうが無いのですがiAdとAdmobはそれぞれ別の広告なので別のdelegateを実装する必要があります。 このまま素直に実装してしまうと表示、非表示の切り替えといった処理やエラーハンドリングが画面ごとに必要になります。

必要な処理をまとめました。

とりあえず広告を貼りたい!というニーズを満たすにもそのままだと結構手間がかかります。 そこで次の様にiAd, Admobの表示を扱うViewクラスを作成しました。

このリポジトリに入っている SimpleAdBannerView というクラスは次の機能を提供します。

  • iAdが読み込めないときにAdmobを表示するViewの提供
  • 広告クリック時のdelegateメソッドの実装
  • 広告から復帰した際のdelegateメソッドの実装
  • Portrait時の上下位置対応

次の様に利用します。

AdSampleViewController.h

#import "SimpleAdBannerView.h"
@interface AdSampleViewController : UIViewController <SimpleAdBannerViewDelegate> {
    SimpleAdBannerView *_adView;
}
@property (nonatomic, retain) SimpleAdBannerView *_adView;
@end

AdSampleViewController.m

#import "AdSampleViewController.h"

@implementation AdSampleViewController
@synthesize _adView;

- (void)viewDidLoad
{
    [super viewDidLoad];

    CGRect mainFrame = [[UIScreen mainScreen] applicationFrame];
    // バナーをアプリ下部に設置する為の設定
    CGRect bannerRect = CGRectMake(
        mainFrame.origin.x,
        mainFrame.size.height,
        320.0,
        50.0
    );
    self._adView = [[SimpleAdBannerView alloc] initWithFrame:bannerRect];
    self._adView.delegate = self;
    [self.view addSubview:self._adView];
    // 広告の呼び出しを開始
    [self._adView requestStart];
}
-(BOOL)adViewActionShoudBegin:(UIView *)banner willLeaveApplication:(BOOL)willLeave {
    NSLog(@"広告クリック時の処理");
    return YES;
}
-(void)adViewActionDidFinish:(UIView *)banner {
    NSLog(@"広告から復帰した際の処理");
}

このクラスを使うことで、UIViewControllerに書くdelegateは広告のクリック時と広告の復帰時の挙動だけでよくなります。 (非常にシンプルなアプリであればそれすら必要無いかもしれません)

あとの広告の表示、非表示といった処理はこのクラスが隠蔽してくれます。 広告をアプリに貼りたいけど面倒だからやってないといった方は是非お試しください。

landscapeに対応していなかったりなどまだまだ微妙なのですが必要になったら手を入れていきます... (pull request歓迎です!)

以上、広告を貼ってみた際の話でした。