Tuesday, March 17, 2015

Cocos2d-x: Tích hợp quảng cáo Admob vào Game (Phần 2)

Hôm nay chúng ta tiếp tục chủ đề Tích hợp quảng cáo Admob vào Game.
Ở phần này chúng ta sẽ tìm hiểu tích hợp trên nền tảng Android, sử dụng môi trường phát triển Eclipse.
Chúng ta cũng sẽ lại đi qua các bước như sau:
1. Tạo thông tin game trong tài khoản Admob của mình
    Tạo các ID cho Banner và Interstital mong muốn
2. Tải về Google Play Service
3. Viết code để hiển thị quảng cáo, điều khiển ẩn hiện quảng cáo theo ý muốn.

1. Tạo thông tin game và các ID

Với bước này mình nghĩ các bạn sẽ có thể tự thao tác được :)

2. Tải về Google Play Service

 Từ trong Eclipse, click Android SDK Manager để mở chức năng SDK Manager, ở đây chúng ta tìm và tải gói Google Play Service

Sau khi tải xong, chúng ta tiếp tục tích hợp Google Play service vào dự án của chúng ta.
- Chọn Propertise, Android



 3. Tích hợp hiển thị quảng cáo

a. Bổ sung các nội dung sau vào file manifest
Bổ sung đoạn sau vào thẻ <application>
<meta-data android:name="com.google.android.gms.version"
                   android:value="@integer/google_play_services_version"/>
        <activity android:name="com.google.android.gms.ads.AdActivity"
                  android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"/>

Bổ sung các permission

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>

b. Sửa đổi lại file AppActivity.java
Cấu trúc mặc định của AppActivity trong Cocos2-dx sẽ như sau

package org.cocos2dx.cpp;
import org.cocos2dx.lib.Cocos2dxActivity;
public class AppActivity extends Cocos2dxActivity {
}
Chúng ta sẽ override lại như sau

public class AppActivity extends Cocos2dxActivity {
    private static AppActivity _appActiviy;
    private AdView adView;
    private InterstitialAd interstitial;

    private static final String AD_UNIT_ID = "ca-app-pub-4323946168772137/31XXXXXXXX";
    private static final String AD_INTERTITIAL_UNIT_ID = "ca-app-pub-4323946168772137/9085XXXXXXX";


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

        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        int width = getDisplaySize(getWindowManager().getDefaultDisplay()).x;

        LinearLayout.LayoutParams adParams = new LinearLayout.LayoutParams(
                width, LinearLayout.LayoutParams.WRAP_CONTENT);

        adView = new AdView(this);
        adView.setAdSize(AdSize.BANNER);
        adView.setAdUnitId(AD_UNIT_ID);

        AdRequest adRequest = new AdRequest.Builder()
                .addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
                .addTestDevice("HASH_DEVICE_ID").build();

        adView.loadAd(adRequest);
        adView.setBackgroundColor(Color.BLACK);
        adView.setBackgroundColor(0);
        addContentView(adView, adParams);

        interstitial = new InterstitialAd(this);
        interstitial.setAdUnitId(AD_INTERTITIAL_UNIT_ID);

        // Begin loading your interstitial.
        interstitial.loadAd(adRequest);       
        _appActiviy = this;
   
    }
   
    public static void hideAd() {
        _appActiviy.runOnUiThread(new Runnable() {

            @Override
            public void run() {
                if (_appActiviy.adView.isEnabled())
                    _appActiviy.adView.setEnabled(false);
                if (_appActiviy.adView.getVisibility() != 4)
                    _appActiviy.adView.setVisibility(View.INVISIBLE);
            }
        });
    }

    public static void showAd() {
        _appActiviy.runOnUiThread(new Runnable() {

            @Override
            public void run() {
                if (!_appActiviy.adView.isEnabled())
                    _appActiviy.adView.setEnabled(true);
                if (_appActiviy.adView.getVisibility() == 4)
                    _appActiviy.adView.setVisibility(View.VISIBLE);
            }
        });

    }

    public static void showInterstitial() {
        _appActiviy.runOnUiThread(new Runnable() {

            @Override
            public void run() {
                _appActiviy.interstitial.show();
            }
        });
    }

    public static void loadInterstitalAgain() {
        _appActiviy.runOnUiThread(new Runnable() {

            @Override
            public void run() {
                AdRequest adRequest = new AdRequest.Builder()
                        .addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
                        .addTestDevice("HASH_DEVICE_ID").build();

                _appActiviy.interstitial.loadAd(adRequest);
            }
        });
    }
   
    @Override
    protected void onResume() {
        super.onResume();
        if (adView != null) {
            adView.resume();
        }
    }

    @Override
    protected void onPause() {
        if (adView != null) {
            adView.pause();
        }
        uiHelper.onPause();
        super.onPause();
    }

    @Override
    protected void onDestroy() {
        adView.destroy();
        super.onDestroy();
    }
}
Đến đoạn này thì khi build và run thì banner quảng cáo đã có thể hiển thị.


https://play.google.com/store/apps/details?id=studio.kensai.KolorShot

Bước tiếp theo chúng ta sẽ làm tương tự bài viết trước, gọi hiển thị quảng cáo Intertitials.
Như ở phần trước, phần này chúng ta sẽ tiếp tục sử dụng EasyNDK, sau khi add thư viện này vào dự án, chúng ta cần phải khai báo chúng trong file Android.mk



Để thực hiện "vận chuyển" lời gọi hàm từ C++ đến Java thông qua EasyNDK, chúng ta sẽ viết 1 lớp trung gian, mục đích lớp này sẽ ""ôm" tất cả các lời gọi native code (có thể cho các mục đích khác như Share Facebook, thanh toán...), ta đặt tên lớp đó là NativeAndroidHelper

NativeAndroidHelper.h

class NativeAndroidHelper
{
public:
    static void hideAd();
    static void showAd();
    static void showInterstitial();
};

NativeAndroidHelper.cpp

#include "NativeAndroidHelper.h"
#include "cocos2d.h"

bool NativeAndroidHelper::isAdShowing = true;

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)

#include "platform/android/jni/JniHelper.h"
#include <jni.h>

const char* AppActivityClassName = "org/cocos2dx/cpp/AppActivity";

void NativeAndroidHelper::hideAd()
{
    cocos2d::JniMethodInfo t;
    if (cocos2d::JniHelper::getStaticMethodInfo(t, AppActivityClassName, "hideAd", "()V"))
    {

        t.env->CallStaticVoidMethod(t.classID, t.methodID);
        t.env->DeleteLocalRef(t.classID);
        isAdShowing = false;
    }
}

void NativeAndroidHelper::showAd()
{
    cocos2d::JniMethodInfo t;
    if (cocos2d::JniHelper::getStaticMethodInfo(t, AppActivityClassName, "showAd", "()V"))
    {

        t.env->CallStaticVoidMethod(t.classID, t.methodID);
        t.env->DeleteLocalRef(t.classID);
        isAdShowing = true;
    }

}

void NativeAndroidHelper::showInterstitial()
{
    cocos2d::JniMethodInfo t;
    if (cocos2d::JniHelper::getStaticMethodInfo(t, AppActivityClassName, "showInterstitial", "()V"))
    {

        t.env->CallStaticVoidMethod(t.classID, t.methodID);
        t.env->DeleteLocalRef(t.classID);
        isAdShowing = true;
    }
}

#else

void NativeAndroidHelper::hideAd() {
    log("hideAd() called");
    isAdShowing = false;
    return; //nothing
}

void NativeAndroidHelper::showAd() {
    log("showAd() called");
    isAdShowing = true;
    return; //nothing;

}

void NativeAndroidHelper::showInterstitial() {
    log("showInterstitial() called");
    return; //nothing;
}
Chúng ta cần chú ý tên của "bộ nhận" receiver AppActivityClassName, AppActivity là lớp nhận thông điệp Java từ các lớp C++, đây là qui định đặt tên của JNIHelper.

Và khi đó, ở trong InGameScene, khi cần hiển thị quảng cáo Interstital, chúng ta chỉ việc gọi thông qua hàm showInterstitial() của lớp này
NativeAndroidHelper::showInterstitial();

https://play.google.com/store/apps/details?id=studio.kensai.KolorShot


Như vậy, đến đây là chúng ta đã hoàn thành việc tích hợp quảng cáo Admob vào Game Cocos2d-x.
Có một số bạn liên hệ mình yêu cầu mình viết luôn phần tích hợp trên Window Phone 8, nhưng rất tiếc mình không có nhiều kinh nghiệm về WP8 nên mình không thể thực hiện tiếp phần đó được :)

No comments:

Post a Comment