This post is also available in:
Chinese
http://blog.csdn.net/liuyuyefz/article/details/17754025
Note from YUYE:
You guys voted for me to update this "How to integrate plugin use it in cocos2d-x in the weekly tutorial vote, so your wish is my command! :]
This tutorial series is now fully up-to-date for Cocos2D-X 2.X/3.X, Android.
The Java Native Interface (JNI) is a programming framework that enables Java code running in a Java Virtual Machine (JVM) to call and be called[1] by native applications (programs specific to a hardware and operating system platform) and libraries written in other languages such as C, C++ and assembly.
Many guys ask me How to integrate the IAP facebook and SDK in cocos2d-x again and again, and thought I’d write a tutorial series based on my experience in case it might be useful to other newcomers.
This tutorial series will walk you through the process of creating a simple game to explain How can you get connect java to c++ with Cocos2D-x, from start to finish. You can follow along with the series, or just jump straight to the sample project at the end of the article.
h3. Jump to
Part 2:
www.part2.com
Part 3:
www.part3.com
of the series.
Downloading and Installing:
You can download cocos2d-x v2.2.2/v3.0beta from : http://www.cocos2d-x.org/download
The architecture and API is many difficult from v2.2.2/v3.0beta
The biggest change is v3.0: Changing namespace from “cocos2d” to “cc”
How to install it :
After you pull down the cocos2d-x v2.2.2/v3.0beta , you’ll want to create project. Open up a Terminal window to the “/Users/Username/cocos2d-x/tools/project-creator/” you downloaded cocos2d-x, and enter the following command:
v2.2.2
python create_project.py -project MyGame -package com.MyCompany.AwesomeGame -language cpp
v3.0beta
python create_project.py -n MyGame -k com.MyCompany.AwesomeGame -l cpp -p /Users/UserName/cocos2d-x-3.0beta/project
And you can open the ios project first under the path "/Users/UserName/cocos2d-x/projects/MyGame/proj.ios
Go ahead and build and run the template as-is. If all works OK, you should see the following:
Change LabelTTF’s text
Before you can change the LabelTTF’s text, you’ll set LabelTTF as a Member Variable in order to set LabelTTF’s text in any functions.
So let’s Open “HelloWorldScene.ccp”
Replace the init method with the following:
2.X version:
bool HelloWorld::init()
{
......
//CCLabelTTF * pLabel = CCLabelTTF::create("Hello World", "Arial", 24);
pLabel = CCLabelTTF::create("Hello World", "Arial", 24);
return this;
}
3.X version:
bool HelloWorld::init()
{
......
//auto label = LabelTTF::create("Hello World", "Arial", 24);
label = LabelTTF::create("Hello World", "Arial", 24);
return this;
}
Add the “LabelTTF declaration” to your HelloWorld class declaration:
2.X version:
class HelloWorld : public cocos2d::CCLayer
{
public:
virtual bool init();
static cocos2d::CCScene* scene();
//LabelTTF declaration
cocos2d::CCLabelTTF * pLabel;
.......
CREATE_FUNC(HelloWorld);
};
3.X version:
class HelloWorld : public cocos2d::Layer
{
public:
static cocos2d::Scene* createScene();
//LabelTTF declaration
cocos2d::LabelTTF * label;
.......
CREATE_FUNC(HelloWorld);
};
Add the following method right after the init method:
void HelloWorld::changeText()
{
pLabel ->setString("My Text!");
}
void HelloWorld::changeText(float t)
{
label ->setString("My Text!");
}
Add the following to your HelloWorld class declaration:
void changeText(float t);
One last thing before you go. You need to actually call the method to change the label’ text! So add the following call to your init method before you return:
changeText(0);
That’s it! Build and run the project, now you should see :
JNI in C++
Next you want the LabelTTF’s text to be change by java – otherwise there wouldn’t be much of a challenge! So let’s add the method for C++ receiving Java’s call to the HelloWorld class, and set up an mark variable for JNI’ thread telling main thread to refresh draw method. Because, opengl can not allow direct change the draw method from others’ thread
Add the following method right before the createScene method:
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include <jni.h>
extern
"C"
{
void Java_org_cocos2dx_cpp_Cocos2dxActivity_changeTTFLabel(JNIEnv* env, jobject thiz,jstring textStr)
{
const char* str;
str = env->GetStringUTFChars(textStr, false);
std::string tempStr(str);
HelloWorld::changeStr = tempStr;
}
}
#endif
We are going to talk about the above one by one.
Part 1:
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#endif
Above is for defining platform. It can only be called when compiling android projects; Others’ platform will not be effect by these code.
Part 2:
#include <jni.h>
It is a head file required by using JNI Method.
Part 3:
extern
"C"
{
...
}
You need to add extern “C” to clarify that you are compiling with C language as the generated function signatures would be different from that of C*+ during compiling process , otherwise you’d get a link error when running.
Part3:
void Java_org_cocos2dx_cpp_Cocos2dxActivity_changeTTFLabel(JNIEnv* env, jobject thiz,jstring textStr)
It goes like Java_package name_class name_method name(Arguments,…)
The arguments:
1.JNIEnv*: reference to JNI environment, which lets you access all the JNI fucntions.
2.jobject: reference to “this” Java object.
3.jstring: JNI defined a jstring type to represent the Java String. The last argument (of JNI type jstring) is the Java String passed into the C program. The return-type is also jstring.
Part 4:
const char* str;
str = env->GetStringUTFChars(textStr, false);
std::string tempStr(str);
HelloWorld::changeStr = tempStr;
Above is for converting the jstring to the const char* then we use a static std::string variable to save the value.
One last thing before you go. You need to clarify the changeStr as a static std::string.So add the following before your JNI method :
std::string HelloWorld::changeStr =" ";
Then add the following to your HelloWorld class declaration:
static std::string changeStr;
Now you can try to build it. if it is not any problem. we go to next step.(more information for JNI refer to:http://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html)
JNI in Java
Before we go to Java. let’s fix one problem. because you can just refresh the GUI in cocos2d-x in the main thread.
So we will create a schedule to detect if the java changed the mark variable.
Then replace HelloWorldScene.cpp with the following code:
V2.X
void HelloWorld::changeText(float t)
{
if (HelloWorld::changeStr.compare(" ") !=0)
{
pLabel ->setString(HelloWorld::changeStr.c_str());
HelloWorld::changeStr =" ";
}
}
V3.X
void HelloWorld::changeText(float t)
{
if (HelloWorld::changeStr.compare(" ") !=0)
{
label ->setString(HelloWorld::changeStr.c_str());
HelloWorld::changeStr =" ";
}
}
Replace the following to the “changeText(0);” call
CCDirector::sharedDirector()->getScheduler()->scheduleSelector(schedule_selector(HelloWorld::changeText),this, 0,false);
Director::getInstance()->getScheduler()->scheduleSelector(schedule_selector(HelloWorld::changeText),this, 0,false);
Now we are done with the C++ part.
Open the page in eclipse:
Before this, make sure you have the android environment to compile cocos2d-x under eclipse ready.
Refer to: http://www.wikihow.com/Set-up-an-Android-Development-Environment
COCOS2D-X V2.2.2
And then at the bottom of the function:
public class TestJniextends Cocos2dxActivity{
……
}
add below:
private static native void changeTTFLabel(String textStr);// works as an intermediary API, allowing java to call the samely named JNI functions in C**.
Finally, at the bottom of
protected void onCreate{
……
}
add and call changeTTFLabel;
5) To view the final result, compile C** and java codes on a real computer
For C++:
Let’s enter the folder cocos2d-x2.2.0/projects/TestJni/proj.android, compile the shell script of build_native.sh
In Windows you’ll need cywin to simulate a linux environment, and in Mac you can just run ./build_native.sh. After a successful compilation, you’ll see something like below. If error occurs, read details to see why.
Now we can compile the java part of android in eclipse.
Click on eclipse – clean.
In the end, connect to a real computer and see label changed from Hello World to Test MyLabel Change!
COCOS2D-X V3.0 beta
for V3.0 you should replace the Cocos2dxActivity.java like this:
package org.cocos2dx.cpp;
import java.util.Timer;
import java.util.TimerTask;
import android.app.NativeActivity;
import android.os.Bundle;
import android.os.Handler;
public class Cocos2dxActivity extends NativeActivity{
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
//For supports translucency
//1.change "attribs" in cocos\2d\platform\android\nativeactivity.cpp
/*const EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
//EGL_BLUE_SIZE, 5, -->delete
//EGL_GREEN_SIZE, 6, -->delete
//EGL_RED_SIZE, 5, -->delete
EGL_BUFFER_SIZE, 32, //-->new field
EGL_DEPTH_SIZE, 16,
EGL_STENCIL_SIZE, 8,
EGL_NONE
};*/
//2.Set the format of window
// getWindow().setFormat(PixelFormat.TRANSLUCENT);
handler.postDelayed( new Runnable()
{
public void run()
{
execute();
}
}, 100 * 1 );
}
private void execute()
{
new Thread( new Runnable()
{
public void run()
{
String a="";
a = String.valueOf((int)(Math.random() * 10+1)) ;
changeTTFLabel("Test MyLabel Change!"+a);
}
}).start();
}
public static native void changeTTFLabel(String textStr);
}
Untitled.png (404.8 KB)
Untitled2.png (634.0 KB)
Untitled3.png (266.0 KB)
openHelloWorld.png (27.3 KB)
changeText2.0.png (13.6 KB)
changeText3.0.png (13.7 KB)
HelloWorld.png (20.4 KB)
MyText.png (15.6 KB)
JNIMethod.png (45.8 KB)
Activity3.0.png (132.5 KB)