向具有JNI的函数发送android.content.Context参数

15

我正在尝试创建一个检查网络连接的方法,需要一个Context参数。JNIHelper允许我调用带参数的静态函数,但是我不知道如何“获取”Cocos2d-x Activity类并将其用作参数。

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;
}

而且C++代码是

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);

你能告诉我为什么你需要这个上下文吗?只是为了得到getSystemService吗? - Nikhil Aneja
1
这不是解决方案,而是isNetworkAvailable的描述符错误。它应该是:“(Landroid/content/Context;)Z”。请注意L和Z。 - Szabolcs Berecz
3个回答

3

Cocos2dxActivity.java: 在Cocos2dxActivity中添加以下代码:private static Activity me = null; 从onCreate方法中删除以下代码:

Cocos2dxActivity.context = getApplicationContext();

在此处替换为:me = this; 用法:
(ConnectivityManager) me.getSystemService(
    Context.CONNECTIVITY_SERVICE);

现在你不需要从Jni中传递上下文... 我知道这并不是解决方案,但对于你的情况,你不需要担心来自Jni的上下文...你只需简单地完成你的工作即可。
希望这能够帮到你。我在我的游戏中使用这种方式发送邮件。 :)

静态属性可能是这里最好的解决方案,而且它也可以通过jni调用进行检索,所以我会将其视为正确的。 - MLProgrammer-CiM
我建议您使用(ConnectivityManager) MyCocos2dxActivity.me.getSystemService(Context.CONNECTIVITY_SERVICE);编辑代码,以便它可以在isNetworkAvailable位于另一个类中时正常工作。 - MLProgrammer-CiM

2
您可以使用以下方法将Context对象传递给JNI:
extern "C" {
JNIEXPORT jboolean JNICALL
Java_yournamespace_yourclassname_methodname( JNIEnv* env, jobject thiz, jobject p_context);
}

在你的Java类中使用以下声明:
public native static boolean methodname(Context p_context);

现在您可以从Java代码中调用本机函数并传递上下文参数。

至于获取您的应用程序类并使用它,我会使用以下代码(在C ++部分):

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);

正确但不正确。您的代码修复了我的调用问题,但我想要的是主应用程序的实际动态上下文,为此我需要先从C++代码中检索它。 - MLProgrammer-CiM
动态上下文是什么意思?您可以使用getApplicationContext()将主应用程序上下文作为参数传递给JNI调用。 - Muzikant
那是我的问题,能做到那件事的CPP代码片段。 - MLProgrammer-CiM

1
我看到的第一个错误是您试图错误地获取方法。
""(android/content/Context;)V"表示您正在请求接收Context作为参数并返回void的方法,而这不是您的情况。
您的调用应该像这样:
jclass aClass = env->FindClass("my/app/TestApp");
env->GetMethodID(aClass, "isNetworkAvailable", "(android/content/Context;)Z");

我不完全确定如何在不破坏或确保其正常工作的情况下将Context传递给JNI。但是,您可以调用getApplication()而不是传递它,并将其用作Context


即使我改变了签名和函数调用,问题仍然存在。该函数所做的是调用OpenFeint,它需要主Activity。我已经在Java代码中修复了它,但我想知道如何从cpp代码中获取应用程序,在其他地方可能需要它。 - MLProgrammer-CiM
@EfEs:这不是你在问题中展示的代码。我不确定该怎么做。我建议你深入研究http://groups.google.com/group/android-ndk以获取答案。 - Macarse

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接