読者です 読者をやめる 読者になる 読者になる

夏までにiPhone アプリつくってみっか!

趣味でiPhone/Androidアプリを開発し、日々勉強した事を書いています。オープンワールド系レースゲームをUnityで開発中です。

【cocos2d-x, Android】AdMob(バナー、インタースティシャル)の実装

cocos2d-x Android   

開発中のAndroid版TravelShooting JPにAdMobを組み込んでみました。
例によってJavaは勉強不足のため、ネットで情報を漁りながら実装しています。

まずは、バナー広告の実装ですが、cocos2d-xのサイトにあるチュートリアルが大変参考になります。

User Tutorial-Integrate AdMob | Cocos2d-x

google-play-services_libライブラリを組み込んだ後、それを認識してくれないような感じで焦りましたが、Eclipseを何度か再起動する事で動くようになりました。
Xcodeと比べてEclipseは不安定な動きをするので悩まされています。
起動時にAndroid SDK Content Loader 0%から進まなくなる事はしょっちゅうで、そのときは根気よく「アクティビティモニタから強制終了→再起動」を繰り返すと復活します。

さて、AdMobの方に話を戻しますと、チュートリアルを参考にした実装だとバナーが画面上部中央に表示されます。TravelShooting JPのタイトル画面は上部にロゴを表示しているので、これは重なってしまうので困ります。

早速ネットで情報を漁ってみるとそのものズバリの情報が見つかりました。

【cocos2dx】admobが中央下に配置できない。 | albatrus.com

LenearLayoutの代わりにFrameLayoutを使い、gravityを設定してやればいいんですね。
なるほど。早速やってみるとバナーが画面下に配置されました。albatrusさん、貴重な情報をありがとうございます!

あと、自分の場合ゲームオーバー画面でバナーを表示したかったのですが、setVilibility()でVISIBLEにしても何故かバナーが見えないという現象が発生しました。しばらく待って次の広告がロードされると表示されるのですが、実は表示されていないときもそこに見えない広告があってクリックできてしまいました。
これではマズいのでEclipseの補完機能で探してみるとbringToFront()というそれっぽいメソッドがありました。試しにsetVilibility()でVISIBLEにしたあとでそれを入れてやるとすぐに表示されるようになり一安心。

バナー広告は以上です。次にインタースティシャル広告に取りかかります。
ググって一番上に出て来るのがこのオフィシャルページ。
インタースティシャル - Google Mobile Ads SDK — Google Developers
サンプルプロジェクトをダウンロードし、それを参考に実装します。しかし、C++から呼ぶ場合はこのままではクラッシュしてしまいます。バナー広告と同様にrunOnUiThread()で実行する必要があるようです。私はここでしばらくハマりました。また、スタティックメソッドにすることで、バナー広告と同様の手続きでアクセスできるようになります。
そして、showInterstitial()で広告を表示した直後に次の広告をロードしておくのですが、newで新しいInterstitialAdインスタンスを作ってやらないとloadAd()できないので注意です。ここもハマりどころかもしれません。

インタースティシャルの部分のJavaの実装はこうなっています。

import org.cocos2dx.lib.Cocos2dxActivity;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.InterstitialAd;

import android.os.Bundle;
import android.util.Log;

public class AppActivity extends Cocos2dxActivity {

	private static final String I_AD_UNIT_ID = "ca-app-pub-XXXXXXXXXXXXXXXX/XXXXXXXXXX";
	private static AppActivity myActivity;
	private static InterstitialAd interstitialAd;

@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		interstitialAd = new InterstitialAd(this);
		interstitialAd.setAdUnitId(I_AD_UNIT_ID);
		adRequest = new AdRequest.Builder()
		.addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
		.build();
		interstitialAd.loadAd(adRequest);

		myActivity = this;

	}

	public static void showInterstitial() {
		myActivity.runOnUiThread(new Runnable() {
			
			@Override
			public void run() {
				if (interstitialAd.isLoaded()) {
					interstitialAd.show();
				} else {
					Log.d("interstitialAd", "Interstital Ad hasn't been loaded.");
				}
				interstitialAd = new InterstitialAd(myActivity);
				interstitialAd.setAdUnitId(I_AD_UNIT_ID);
				AdRequest adRequest = new AdRequest.Builder()
				.addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
				.build();
				interstitialAd.loadAd(adRequest);
			}
		});
	}
}

C++からはこちらの記事のJNIBridge.cppと同じ方法でアクセス可能です。tf.hateblo.jp


私はAdMobメディエーションでAdMobとnendを使っているのですが、インタースティシャルの方はどうも上手く行きません。
インタースティシャル広告の表示中はアプリの処理は強制的に停止させられ、広告のXボタンを押して消す事によりアプリが動き出すというのが正しい動作のはずです。AdMobのインタースティシャル広告を表示する場合はそのように動作しています。
nendの場合、広告は表示される(Nexus 7 (2013)で見た場合、全画面ではなく画面中央に小さめに表示)のですが、その裏でアプリが動き出してしまい、広告をゆっくり見ている余裕はありません。
この部分の処理はアプリ側では直しようがないのでとりあえずnendはインタースティシャルのメディエーションから外しました。
なお、nendのバナー広告の方は問題なくAdMobメディエーションで動いています。