JNI C++ Java method invocation simple example

Hi all,

I am trying to implement a way to check device native resolution, and as it seems, at least with Android one would need to use JNI for that.
Been goggling and following some guides online, but still no luck. I guess my understanding of JNI logic is broken :confused:

For example, a simple dummy method returning a string …

Java part:

public class Common {
    public static String getResolution()
    {
        // Dummy method for now...

        return "320x240";
    }
}

C+ part:*
JNI
Where do add this?
I see some people modify the framework bindings “cocos2dx\platform\android\jni”.
But I would like to leave the framework intact, so I’m adding it to project folder “proj.android\jni\myapp\main.cpp”
<pre>
// Get device resolution
JNIEXPORT jstring JNICALL Java_com_myapp_Common_getResolution
{
// Dummy for now…
jstring jstr = env->NewStringUTF;
return jstr;
}
</pre>
This compiles fine, but now how to access this method from C
+ project classes ?
**from project Classes*

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include  // is this needed ?
char* value = Java_com_myapp_Common_getResolution();
#endif

This won’t compile successfully, method not declared.
Can someone help me understand the logic of JNI ?

error: 'Java_com_myapp_Common_getResolution' was not declared in this scope

Ok, managed to achieve my goal.
I think the approach in first comment is meant to be used in invoking C*+ method from Java.
So my goal was to invoke a Java method from C**, more precisely to get android device native resolution.
Let’s start with Java part:
We need to define the method we want to invoke from C*+.
I’ll create a static method and since I’ll need to get the class instance in order to system services, I’ll add a static private member to hold it’s value.

public class MyGame extends Cocos2dxActivity{

   // assign class instance
    static private MyGame instance;

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

    // assign self instance
    Samecolor.instance = this;
    }

        (...)

    // Get resolution size
    static public int[] getResolution()
    {
        // get application
        Context context = Samecolor.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 now the C++ part:

All JNI core is meant to be used with Android, so we’ll need to wrap some code #if #endif directives.
If not it will fail to compile in any all other platforms.

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
// include JniHelper.h
#include "platform\android\jni\JniHelper.h"
#endif

#include "cocos2d.h"

USING_NS_CC;

(...)

static CCSize getDeviceResolutionX()
{
    CCSize res = CCSize(0.0f, 0.0f);

    #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
    JniMethodInfo t;
    // get method 'getResolution' which returns int array '()[I' from java package 'com.mygame' & 'MyGame' class
    if (JniHelper::getStaticMethodInfo(t,
        "com/mygame/MyGame",
        "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);
        }
    }
    #endif

    // return CCSize
    return res;
}

Feel free to point out possible issues/performance, I’m sure there’s room to improvement :slight_smile:

1 Like

Good examples can be found at cocos2d-x upSL scoreloop extension git repo https://github.com/ursine-paw/upSL/tree/master/android

Here: https://github.com/Piperoman/CCSocialNetwork

You have another example to make calls from C*+ to Java, and Java to C*+ in Android, and objective C.

Hope its help.

Hey lumendes,

Would I be able to use this technique for a commercial application I’m working on?

Thanks,
-MDKG

@MDKG Yes sure :slight_smile:

I created a demo implementation of C++ to Java communication in Cocos2d-x v.3.2. Source here:

https://github.com/ElliotMebane/Cocos2d-x_CPP_to_Java_via_JNI_Samples

Stefan Nguyen’s post that was a foundation for my work:

http://stnguyen.com/cocos2d-x/call-java-functions-from-cpp.html