JNI Integration

My project name is Test0001 (Package: com.WBS.Test0001)
My file looks like this:

`import org.cocos2dx.lib.Cocos2dxActivity;

import android.content.Context;
import android.os.Bundle;
import android.view.Display;
import android.view.WindowManager;

public class Test0001 extends Cocos2dxActivity{

static private Test0001 instance;

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

    Test0001.instance = this;
}

static {
     System.loadLibrary("game");
}

public static int[] getResolution()
    {
        // get application
        Context context = Test0001.instance;

        // get window manager and display
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();

        // create array with size
        int size[] = {display.getWidth(), display.getHeight()};

        // return size
        return size;
    }

}`

and the HelloWorldScene.cpp looks like this

`#include “HelloWorldScene.h”
#include “SimpleAudioEngine.h”
//#include “jni/JniHelper.h”
#include “…/platform/android/jni/JniHelper.h”

using namespace cocos2d;
using namespace CocosDenshion;

CCScene* HelloWorld::scene()
{
// ‘scene’ is an autorelease object
CCScene *scene = CCScene::create();

// 'layer' is an autorelease object
HelloWorld *layer = HelloWorld::create();

// add layer as a child to scene
scene->addChild(layer);

// return the scene
return scene;

}

// on “init” you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !CCLayer::init() )
{
return false;
}

/////////////////////////////
// 2. add a menu item with "X" image, which is clicked to quit the program
//    you may modify it.

// add a "close" icon to exit the progress. it's an autorelease object
CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
                                    "CloseNormal.png",
                                    "CloseSelected.png",
                                    this,
                                    menu_selector(HelloWorld::menuCloseCallback) );
pCloseItem->setPosition( ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20) );

// create menu, it's an autorelease object
CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
pMenu->setPosition( CCPointZero );
this->addChild(pMenu, 1);

/////////////////////////////
// 3. add your codes below...

// add a label shows "Hello World"
// create and initialize a label
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 - 20) );

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

// add "HelloWorld" splash screen"
CCSprite* pSprite = CCSprite::create("HelloWorld.png");

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

// add the sprite as a child to this layer
this->addChild(pSprite, 0);

CCSize res = CCSize(0,0);

JniMethodInfo t;
    // get method 'getResolution' which returns int array '()[I' from java package 'com.mygame' & 'MyGame' class
    if (JniHelper::getStaticMethodInfo(t,
        "com/WBS/Test0001",
        "getResolution",
        "()I"))
    {
        // get int array
        jintArray ret = (jintArray)t.env->CallObjectMethod(t.classID, t.methodID);
        // delete reference
        t.env->DeleteLocalRef(t.classID);
        if (ret)
        {
            // get array values
            jint *oarr = t.env->GetIntArrayElements(ret, NULL);

            // assign array values to CCSize
            res.width = (float)oarr[0];
            res.height = (float)oarr[1];

            // release array values
            t.env->ReleaseIntArrayElements(ret, oarr, NULL);
        }
    }
    CCLog("resolution is %f %f",res.width, res.height);

return true;

}

void HelloWorld::menuCloseCallback(CCObject* pSender)
{
CCDirector::sharedDirector()->end();

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}
`

but when I run this on the emulator I get the following error:
" VM aborting
Fatal Signal 11 (SIGEGV) at 0xdeadd00d (code=1), thread 1815 (Thread - 132) "

If i comment the JNI calling in the cpp, then HelloWorldScene.cpp works fine.

Any help?
Using the latest version of cocos2d-x.

Bump! anyone?

You can check a very good implementation of jni integration from CocosDenshion…
CocosDenshion-android and CocosDenshion-include

if (JniHelper::getStaticMethodInfo(t,
“com/WBS/Test0001”,
“getResolution”,
“()I”)) —> should be “()[I”

@Minggo Zhang: Does not work. Still the same error :frowning:

Im finding it a little difficult to follow the CocosDenshion flow. Are there any other options? No tutorial out there thats with the current version of cocos2dx? or if some could tell me what Im doing wrong here.

This article may help you, it’s writen in Chinese, but I think you can read the code.
http://blog.csdn.net/kafei_kings/article/details/8106744

Thanks for the link.

If I call the function on a jObject and not as a static function(as below), it works.

JniMethodInfo t; JniMethodInfo minfo; jobject jobj; if(JniHelper::getStaticMethodInfo(minfo, "com/WBS/Test0001/Test0001", "cppCall_logsth", "()Ljava/lang/Object;")){ jobj = minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID); if(JniHelper::getMethodInfo(minfo, "com/WBS/Test0001/Test0001", "getResolution", "()F")){ jfloat val = minfo.env->CallFloatMethod(jobj, minfo.methodID); width = val; } }
corresponding java functions are
`public float getResolution()
{
Context context = Test0001.instance;

    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();

    // create array with size
    int size[] = {display.getWidth(), display.getHeight()};
    Log.i("MyActivity", "width is " + display.getWidth());

    return display.getWidth();
}

public static Object cppCall_logsth(){
Log.i(“cppCall”, “test~~~~!!!”);
return Test0001.instance;
}`

But if i try to call it on a static method it crashes. I have tried a void method also
@
if (JniHelper::getStaticMethodInfo(t,
“com/WBS/Test0001/Test0001”,
“getResolution”,
“()V”))
{
t.env->CallStaticVoidMethod(t.classID, t.methodID);
}
@
java corresponding function is

@
public static void getResolution()
{
return ;
}
@

Can anyone guide me so as why this is happening? In the first case, the “CallStaticObject” function works, so why does not the “CallStaticIntMethod” not work?

Fixed it! :slight_smile:

It’s interesting you could call a non-static function with JNI while other peoples having trouble with that issue. Could you provide a simple example? I can’t understand what the jobject is.

I’m not understand what the jobject is too.