Code Bit: How to use JNI in Cocos2dx Android?

Thank you, Bojun for helping me understand all this 🙂

You can first read up the Cocos2dx documentation on this: http://www.cocos2d-x.org/projects/cocos2d-x/wiki/How_to_use_jni

Basically JNI is this thing that allows you to call Java code from C++ and vice versa.

I’m gonna post a very round about code that I think shows how to do it both ways.

First off, in Java (my class name is sample.java), I have two additional methods:

public static native void printSomething();

public static void printSomethingFromJava()
{    printSomething();
}

The printSomething method corresponds to a method in my C++, while printSomethingFromJava is a method that is called from my C++.

So far so good?

And then in C++ (HelloWorld.cpp), I have the method that corresponds to the printSomething method in Java:

void Java_com_purple_sample_sample_printSomething(JNIEnv *env, jobject obj)
{    CCNotificationCenter::sharedNotificationCenter()->postNotification(“printSomethingInCPP”, NULL);
}

Basically, when you call printSomething in sample.java, this method is called.

So there, we can call a method in C++ from Java.

Notice the CCNotification (thank you so much, Bojun for teaching me this). Since I can’t call anything in HelloWorld, because it’s not part of the scene, I need to use CCNotification to call any methods from Hello World.

In order for a CCNotification to be called you need to add an observer first, so somewhere in HelloWorld’s init method:

CCNotificationCenter::sharedNotificationCenter()->addObserver(this, callfuncO_selector(HelloWorld::printSomethingInCPP), “printSomething”, NULL);

printSomethingCPP is a method in HelloWorld that essentially adds a CCLabel to our scene:

void HelloWorld::printSomethingInCPP()
{    CCLabelTTF* pLabel = CCLabelTTF::create(“Hello World”, “Thonburi”, 34);

    // ask director the window size
    CCSize size = CCDirector::sharedDirector()->getWinSize();

    // position the label on the center of the screen
    pLabel->setPosition( ccp(size.width / 2, size.height/2) );

    // add the label as a child to this layer
    this->addChild(pLabel);
}

Still following?

So now, we can call a method in C++ from Java, and we use CCNotification to call another method that’s in the HelloWorld scene.

Next up! Calling a Java method from C++.

Remember the printSomethingFromJava method? That is a method that we will call from our C++.

So in C++, I created a method named printSomethingFromJava, and it contains some of these:

void HelloWorld::printSomethingFromJava()
{    JniMethodInfo t;
    if(JniHelper::getStaticMethodInfo(t, “com/purple/sample/sample”, “printSomethingFromJava”, “()V”))
    {    t.env->CallStaticVoidMethod(t.classID, t.methodID);
        // delete reference
        t.env->DeleteLocalRef(t.classID);
    }
}

Now, this code is what calls the printSomethingFromJava method in Java.

I call the printSomethingFromJava method in HelloWorld.cpp in its init method, somewhere after the CCNotificaton Add Observer.

This blog has a list of methods, return calls etc. for Android JNI: http://blog.csdn.net/lizhiguo0532/article/details/7219357.

Okay, so it’s a little confusing, basically what my code does is, HelloWorld (C++) calls a method in sample (java), and sample (java) then calls a method in HelloWorld (C++).

Why do I do this? It’s just an exercise that was pretty helpful for me (I think) to understand the confusing thing that is JNI.

*bows*