This demo project shows how to integrate the Unity Ads SDK into a Cocos2Dx Android game
*Asume you already have a Cocos2d-x and Android native development environment. If you aren't, Cocos2d-x and Android NDK resources are for your references.
Create a Game Project on the Unity Ads Dashboard
- Log into the dashboard using your UDN Account
- Create a new game project
- Look for your Android Game ID in the project, a 7-digit number that you will use in your integration
- Download the Unity SDK from https://github.com/Applifier/unity-ads-sdk
- Unzip the project, and locate
unity-ads.aar
. This package contains all binaries and configuration files for Unity Ads SDK. - You start importing Unity Ads by selecting 'File' > 'New' > 'New Module' and choosing 'Import .JAR/.AAR Package'. Select the downloaded aar file from your computer and import the file.
- Now you need to add the imported Unity Ads module as a dependency to your own module. Right click your app module, select 'Open Module Settings' and open 'Dependencies' tab. Add a new dependency as 'Module Dependency' and select Unity Ads module.
Import UnityAds to your AppActivity
-
Import UnityAds package
UnityAds
andIUnityAdsListener
in AppActivity fileimport com.unity3d.ads.android.IUnityAdsListener; import com.unity3d.ads.android.UnityAds;
-
Make your AppActivity implements
IUnityAdsListener
protocolpublic class AppActivity extends Cocos2dxActivity implements IUnityAdsListener {
-
Implement
IUnityAdsListener
methods in AppActivitypublic void onHide(){ Log.d("[Ads Test Lifecycle]", "onHide"); } public void onShow(){ Log.d("[Ads Test Lifecycle]", "onShow"); } public void onVideoStarted(){ Log.d("[Ads Test Lifecycle]", "onVideoStarted"); } public void onVideoCompleted(String itemKey, boolean skipped){ Log.d("[Ads Test Lifecycle]", "[onVideoCompleted] with key="+itemKey+", and skipped="+skipped); } public void onFetchCompleted(){ Log.d("[Ads Test Lifecycle]", "onFetchCompleted"); } public void onFetchFailed(){ Log.d("[Ads Test Lifecycle]", "onFetchFailed"); }
-
Initialize UnityAds in
UnityAdsInit
method.@Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); initAd(); } @Override protected void onResume() { super.onResume(); UnityAds.changeActivity(this); } private void initAd(){ Log.d("[Ads Test]", "initializing ad"); UnityAds.setTestMode(true); UnityAds.init((Activity) this, "1044314", (IUnityAdsListener) this); }
- Create UnityAdsNDK.java file.
- Add static methods for native to call.
```Java
import com.unity3d.ads.android.UnityAds;
import android.util.Log;
public class UnityAdsNDK {
public static boolean canUnityAdsShow() {
Log.d("[Ads Test]", "canUnityAdsShow");
return UnityAds.canShow();
}
public static void showUnityAds() {
Log.d("[Ads Test]", "showUnityAds");
UnityAds.show();
}
}
```
- You need open the Cocos2d-x project root folder by using Android Studio in order to see the JNI C++ folder. The folder is located at
{YourCocos2dxProjectRoot}/proj.android-studio/app/jni/
, Create the header file and C++ implementation file UnityAdsBridge.h and UnityAdsBridge.cpp - Move UnityAdsBridge.h to Classes folder in order to be called thru class path.
- Add the header file and implementation C++ file in Android.mk
LOCAL_SRC_FILES := hellocpp/main.cpp \
hellocpp/UnityAdsJni.cpp \
../../../Classes/AppDelegate.cpp \
../../../Classes/HelloWorldScene.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../Classes \
hellocpp/UnityAdsJni.h
- Add below source code in the header file
```Cpp
#include <jni.h>
#include "platform/android/jni/JniHelper.h"
#ifdef __cplusplus
extern "C" {
#endif
extern bool canShowJni();
extern void showJni();
#ifdef __cplusplus
}
#endif
```
- Add below implementation in the C++ implementation file.
```Cpp
#include "UnityAdsBridge.h"
#include <android/log.h>
#include "AppDelegate.h"
#include "cocos2d.h"
#define LOG_TAG "UnityAdsBridge"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define CLASS_NAME "org/cocos2dx/cpp/UnityAdsNDK"
using namespace cocos2d;
#ifdef __cplusplus
extern "C" {
#endif
bool canShowJni()
{
JniMethodInfo methodInfo;
if (! JniHelper::getStaticMethodInfo(methodInfo, CLASS_NAME, "canUnityAdsShow", "()Z"))
{
LOGD("Failed to find static method of canUnityAdsShow");
return false;
}
jboolean ans = (jboolean)methodInfo.env->CallStaticBooleanMethod(methodInfo.classID, methodInfo.methodID);
bool ret = false;
if(JNI_TRUE == ans)ret = true;
return ret;
}
void showJni()
{
JniMethodInfo methodInfo;
if (! JniHelper::getStaticMethodInfo(methodInfo, CLASS_NAME, "showUnityAds", "()V"))
{
LOGD("Failed to find static method of showUnityAds");
return;
}
methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID);
}
#ifdef __cplusplus
}
#endif
```
- Import
#include "UnityAdsBridge.h"
in HelloWorldScene.h file. - In
HelloWorldScene.h
file, move the menu button to a easy to click place and make it bigger also for easy clicking.
auto closeItem = MenuItemImage::create("coin_1.png", "coin_1.png",
CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
closeItem->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
- Replace end game function to show ads.
if(canShowJni()) {
showJni();
}
//Director::getInstance()->end();
We just update text from "Hello World" to "Rewarded" this time.
- Add reward api in UnityAdsBridge.h header file.
JNIEXPORT void JNICALL Java_org_cocos2dx_cpp_UnityAdsNDK_reward (JNIEnv *, jobject, jstring s);
static char* jstringTostring(JNIEnv* env, jstring jstr);
- Add reward implementation in the UnityAdsBridge.cpp file.
JNIEXPORT void JNICALL Java_org_cocos2dx_cpp_UnityAdsNDK_reward (JNIEnv * env, jobject jobj, jstring zoneid)
{
char* ret = NULL;
ret = jstringTostring(env, zoneid);
LOGD("placement id = %s", ret);
auto scene = Director::getInstance()->getRunningScene()->getChildren().at(1);
if (typeid(*scene) == typeid(HelloWorld)) {
static_cast<HelloWorld*>(scene)->rewardPlayer(ret);
} else {
LOGD("gameScene is still NULL");
}
}
static char* jstringTostring(JNIEnv* env, jstring jstr)
{
char* rtn = NULL;
// convert jstring to byte array
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = env->NewStringUTF("utf-8");
jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray barr= (jbyteArray)env->CallObjectMethod(jstr, mid, strencode);
jsize alen = env->GetArrayLength(barr);
jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
// copy byte array into char[]
if (alen > 0)
{
rtn = new char[alen + 1];
memcpy(rtn, ba, alen);
rtn[alen] = 0;
}
env->ReleaseByteArrayElements(barr, ba, 0);
return rtn;
}
- Add native reward api call in Android layer when video completed.
Add native interface in
UnityAdsNDK
class.
public static native void reward(String placementId);
Add call of the native interface in AppActivity
class.
public void onVideoCompleted(String itemKey, boolean skipped){
UnityAdsNDK.reward("rewardedVideo");
Log.d("[Ads Test Lifecycle]", "[onVideoCompleted] with key="+itemKey+", and skipped="+skipped);
}
- Update game logic update label text from "Hello World" to "Rewarded".
Add
rewardPlayer
interface in HelloWorld C++ header.
void rewardPlayer(char* rewardId);
Upgrade "Hello World" label to a private field in HelloWorld C++ header.
private:
cocos2d::Label* _label;
Change the declaration and use of label to use _label in HelloWorld C++ class.
_label = Label::createWithTTF("Hello World", "fonts/Marker Felt.ttf", 60);
_label->setPosition(Vec2(origin.x + visibleSize.width/2,
origin.y + visibleSize.height - _label->getContentSize().height));
this->addChild(_label, 1);
Add implementation of rewardPlayer
function in HelloWorld C++ class.
void HelloWorld::rewardPlayer(char* rewardId) {
_label->setString("Rewarded!");
}
Finally, we finished a rewarded video.
For more information, check out the Android Integration Guide, the support Forum, or contact [email protected]