Sending a android.content.Context parameter to a function with JNI
Asked Answered
H

3

15

I am trying to create a method that checks for internet connection that needs a Context parameter. The JNIHelper allows me to call static functions with parameters, but I don't know how to "retrieve" Cocos2d-x Activity class to use it as a parameter.

public static boolean isNetworkAvailable(Context context) {
    boolean haveConnectedWifi = false;
    boolean haveConnectedMobile = false;
    ConnectivityManager cm =
        (ConnectivityManager) context.getSystemService(
    Context.CONNECTIVITY_SERVICE);
    NetworkInfo[] netInfo = cm.getAllNetworkInfo();
    for (NetworkInfo ni : netInfo) {
        if (ni.getTypeName().equalsIgnoreCase("WIFI"))
            if (ni.isConnected())
                haveConnectedWifi = true;
        if (ni.getTypeName().equalsIgnoreCase("MOBILE"))
            if (ni.isConnected())
                haveConnectedMobile = true;
    }
    return haveConnectedWifi || haveConnectedMobile;
}

and the c++ code is

JniMethodInfo methodInfo;
if ( !JniHelper::getStaticMethodInfo( methodInfo,
    "my/app/TestApp", "isNetworkAvailable", "(Landroid/content/Context;)Z")) {
        //error
        return;
}
CCLog( "Method found and loaded!");
methodInfo.env->CallStaticBooleanMethod( methodInfo.classID,
methodInfo.methodID);
methodInfo.env->DeleteLocalRef( methodInfo.classID);
Hemelytron answered 12/4, 2012 at 12:32 Comment(2)
Can you tell me why do you need this context? Just to get getSystemService ?????Runt
This is not the solution, but the descriptor for isNetworkAvailable is wrong. It should be: "(Landroid/content/Context;)Z". Note the L and ZTunicate
R
3

Cocos2dxActivity.java: Add this line to Cocos2dxActivity: private static Activity me = null; Remove this line from onCreate:

Cocos2dxActivity.context = getApplicationContext();

In its place put: me = this;

use :

(ConnectivityManager) me.getSystemService(
    Context.CONNECTIVITY_SERVICE);

Now you don't need to pass the context from your Jni... I know this is not the solution but for your case you don't need to worry about context from Jni.. You can simply do your work.

Hope this helps.. I used this way to send mail from android in my game. :)

Runt answered 27/4, 2012 at 6:33 Comment(2)
Static attribute is probably the best solution here, and it also is retrievable with jni calls so I'll give it as correct.Hemelytron
I advice you edit the code with (ConnectivityManager) MyCocos2dxActivity.me.getSystemService( Context.CONNECTIVITY_SERVICE); so it shows it can work even if the isNetworkAvailable is in another class.Hemelytron
P
2

You can pass Context object to JNI using the following method:

extern "C" {
JNIEXPORT jboolean JNICALL
Java_yournamespace_yourclassname_methodname( JNIEnv* env, jobject thiz, jobject p_context);
}

on your java class use the following declaration:

public native static boolean methodname(Context p_context);

Now you can call the native function from your java code and pass a context a parameter.

as for getting your app class and use it, I'd use the following code (in the C++ part):

jclass yourAppClass = env->FindClass("my/app/TestApp");
jmethodID someMethodId = env->GetStaticMethodID(yourAppClass , "methodName", "(Landroid/content/Context;)Z");
jboolean retval = env->CallStaticObjectMethod(yourAppClass , someMethodId , p_context);
Peonir answered 28/4, 2012 at 11:18 Comment(3)
Correct but incorrect. Your code fix my call problems, but what I want is the actual dynamic context of the main application, and for that I need to retrieve it first from the c++ code.Hemelytron
What do you mean by dynamic context? The main application context can be passed as an argument to your JNI call using getApplicationContext()Peonir
And that was my question, the snippet that does that, in CPP.Hemelytron
H
1

The first error I see is that you are trying to get the method incorrectly.

"(android/content/Context;)V" means you are asking for a method that receives Context as a parameter and returns void which is not your case.

Your call should be something like this:

jclass aClass = env->FindClass("my/app/TestApp");
env->GetMethodID(aClass, "isNetworkAvailable", "(android/content/Context;)Z");

I am not completely sure how to pass a Context to JNI without breaking things or being sure it will work. But instead of passing it, you can call getApplication() and use it as a Context.

Halfprice answered 24/4, 2012 at 13:24 Comment(2)
Even if I change the signature and function call, the problem remains. What the function does is to call OpenFeint, which requieres the main Activity. I sort of fixed it in the java code, but I would like to know how to get the app from cpp code in case I need it somewhere else.Hemelytron
@EfEs: That's not the code you are showing in your question. I am not sure how to do it then. I would recommend you digging into groups.google.com/group/android-ndk to learn the answer.Halfprice

© 2022 - 2024 — McMap. All rights reserved.