2013年2月17日日曜日

VGSでの広告表示(Tap for Tap)

先日、InvaderBlock2のフリー版(広告付き)を公開しました。
広告の実装には、Tap for Tapを採用してみました。
私は、どちらかというと広告ビジネスに否定的な見解を示していたので、その釈明を兼ねて考え&TIPS(VGSのアプリで広告を実装する方法)を記しておきます。

広告会社の概要

Tap for Tapは、カナダ(米国のブリティッシュコロンビア州)に拠点をおく広告会社です。
私のアプリ事業は、北米方面を中心に展開しているので、そっち方面の会社の方が良かろうという判断です。米国本土の方が良いかもしれませんが、サービス内容が興味深かったので、そこにしてみました。デベロッパー数は6,000人前後。(まだ新興企業ですね)

サービス概要

Tap for Tapの場合、プロモーション(ユーザ獲得)と収益化のバランスを、任意に調整できます。
例えば、広告で得た収益の全てをプロモーションに使うことができます。
# 実質的な費用対効果については、まだ十分なデータが集まっていないので未確認。

利用した経緯

NOKOGI Riderの販売を開始してもうすぐ半年ぐらい経過します。
その間の販売実績は、現時点で57本ぐらいと不調です。
ゲームそのものは面白いと思います。
しかし、如何せんプロモが弱すぎることが売れない原因かもしれません。
マネタイズのみの広告アプリというのは、未だにちょっと疑心暗鬼しています。
しかし、プロモ用途でちょっと使ってみるぐらいなら良いんじゃないかと思い始めました。

ただし、広告を入れれば結構沢山のパーミッション要求が必要になります。
NOKOGI Riderに関しては、それで汚したくないと考えました。
そこで白羽の矢が立ったのが「InvaderBlock2」です。

「InvaderBlock2」は、GooglePlayでの販売テスト用にリリースしたアプリです。
ゲームそのものの面白さは中々だと思ってます。
しかし、やはり実質的に有償販売だけなので、サッパリ売れません。
(一応、1年で10本ぐらい売れましたが)

ついでに、InvaderBlock2は、広告アプリで成功するために必要な要素を持っています。
恐らく、広告アプリとしての潜在能力は、NOKOGI Rider以上です。
そう思っていた矢先、Tap for Tapの担当者から「InvaderBlock2に広告を載せてくれ」というeメールがあり、サービスを確認したところ私の方針(プロモーション強化)にマッチしていると思ったので、それを利用してみることにしました。

VGSアプリでの広告の実装方法(基本編)

とても簡単です。以下、InvaderBlock2のソースコード(Java側)の抜粋で説明します。
    @Override
    public void onCreate(Bundle savedInstanceState) {
        try {
            ~VGS関連の初期化(中略)~
            } else {
                // View の設定
                mMainView=new VgeSurfaceView(this);
                mLayout=new FrameLayout(this);
                mLayout.addView(mMainView);
                getWindow().setContentView(mLayout);
                TapForTap.initialize(this, "自分のAPIキー");
                mAdView = new AdView(this);
                DisplayMetrics metrics = getResources().getDisplayMetrics();
                int width = metrics.widthPixels;
                int height = (int)(50 * (width / 320.0));
                LinearLayout.LayoutParams myLayoutParams = new
                                        LinearLayout.LayoutParams(width, height);
                mAdView.setLayoutParams(myLayoutParams);
                mAdParam=new FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams.MATCH_PARENT,
                    FrameLayout.LayoutParams.WRAP_CONTENT,
                    Gravity.BOTTOM);
                mLayout.addView(mAdView,mAdParam);
                mAdPut=true;
            }
        } catch(Exception e) {
            Log.e(LOG_TAG, "AN EXCEPTION DETECTED.", e);
        }
    }
前半の初期化処理は、VGS固有の初期化処理なので中略しました。
ポイントは青色の網掛け部分です。
広告の処理は、ゲームとは別のビューで実装します。
大まかに、VGSのプログラムに広告を実装する場合、次のような実装をすればOKです。
(1) FrameLayoutクラスのオブジェクト(mLayout)を準備
(2) ゲーム本体のビュー(mMainView)を作成し、mLayoutに追加。
(3) 広告表示用のビュー(mAdView )を作成し、mLayoutに追加。
なお、実装中の緑色の網掛け部分は、広告ビューのスタイルを設定する処理です。
この部分は、レイアウトのxmlでも良いかもしれません。(サンプルはその方式でした)

メイン処理(C言語)との連携処理

広告を表示しっぱなしのアプリであれば、上記の実装でOKです。
ただし、ゲームの場合、ゲームのプレイ中に広告表示がされるのはハッキリ言って邪魔です。
そこで、広告の表示をON/OFFできる仕組みの実装方法を解説します。

VGSの場合、C言語で実装しているメイン処理に広告のON/OFFなどのオペレーションを要求するためのインタフェースを実装する必要があります。下記のような感じで良いと思います。
    /*
     *------------------------------------------------------------------------
     * Java側への要求を取得する (JNI)
     *------------------------------------------------------------------------
     */
    public static native int getRequest();
※数値(jint)でオペレーションを返す仕様にします(0 = None / 1 = put ads / 2 = delete ads)

そして、VgeSurfaceViewのスレッドでオペレーション(0以外)を取得した場合、アクティビティクラスでそれを処理できるようにするために、アクティビティクラスにハンドラ関数を実装します。
    public Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            switch(mRequest) {
                case 1: //広告を表示
                    if(!mAdPut) {
                        mLayout.addView(mAdView,mAdParam);
                        mAdPut=true;
                    }
                    break;
                case 2: //広告を削除
                    if(mAdPut) {
                        mLayout.removeView(mAdView);
                        mAdPut=false;
                    }
                    break;
            }
            mRequest=-1;
        }
    };

VgeSurfaceView側の実装はこんな感じでOKです。

    public VgeSurfaceView(Context context) {
        super(context);
        act=(IBLOCKA)context;
        vram=Bitmap.createBitmap(XSIZE,YSIZE,Bitmap.Config.RGB_565);
        vram.setDensity(Bitmap.DENSITY_NONE);
        vramRect=new Rect(0,0,XSIZE,YSIZE);
        getHolder().addCallback(this);
    }


    @Override
    public void run() {
        SurfaceHolder holder=getHolder();
        Canvas canvas;
        int rc=0;
        int rq;
        while (isAttached) {
            canvas=null;
            try {
                rc=IBLOCKA.setVram(vram);
                canvas=holder.lockCanvas();
                if(null!=canvas) {
                    canvas.drawBitmap(vram,vramRect,screenRect,screenPaint);
                }
            } finally {
                if(null!=canvas) holder.unlockCanvasAndPost(canvas);
                if(rc!=0) break;
            }
            rq=IBLOCKA.getRequest();
            if(0!=rq) {
                IBLOCKA.mRequest=rq;
                act.handler.sendEmptyMessage(0);
            }
        }
        if(0!=rc) {
            System.exit(0);
        }
    }
getRequestで0以外を取得した場合、値をアクティビティクラスのメンバ変数にセットして、sendEmptyMessage関数でハンドラ関数を実行して、1(広告を表示)または2(広告を削除)を実行します。
実は私はJavaが苦手なので、あまりJavaっぽくない作り方かも。
この辺りは、お好みでアレンジしてください。

概ねこんな感じの実装を使えば、VGSのアプリに広告を実装できます。
広告の実装方法については、AdMobなどの他の広告会社のものでも、基本的なことは概ね同じじゃないかと思います。





0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。

合理的ではないものを作りたい

ここ最近、実機版の東方VGSの開発が忙しくて、東方VGSの曲追加が滞っています。 東方VGS(実機版)のデザインを作りながら検討中。基本レトロUIベースですがシークバーはモダンに倣おうかな…とか pic.twitter.com/YOYprlDsYD — SUZUKI PLAN (...