5

Please bear with me, I am an iPhone developer and this whole android this confuses me a bit.

I have some c++ methods that are called from a cocos2d-x CCMenuItem. Therefore I cannot send any parameters, according to the docs.

I need to open a url with the android browser which will require me to call a JAVA function to start a new intent.

I understand that I need to create a VM, however the below code gives me the error:

jni/../../Classes/OptionsScene.cpp:184: error: 'JNI_CreateJavaVM' was not declared in this scope

I was looking at this thread: Calling a java method from c++ in Android

But he uses parameters, and I can't do that. And I don't see where those are in his code to just make them myself.

I don't know what the string should be in the 'Find Class' method. Also, I assume it is pretty terrible to create a new VM instance in every method I need to call. How would I create one as a singleton to use across the board?

This is my c++ code called by my menu item:

#include <jni.h>
...
JavaVM *vm; // Global
...
void OptionsScene::website(){
JNIEnv *env;
JavaVMInitArgs vm_args;
vm_args.version = JNI_VERSION_1_2;
vm_args.nOptions = 0;
vm_args.ignoreUnrecognized = 1;

jint result = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args); // This line still errors

jclass clazz = env->FindClass("com/prndl/project/WebExecute");
jmethodID method = env->GetMethodID(clazz, "website", "(Ljava/lang/String;)V");
env->CallVoidMethod(NULL,method);

vm->DestroyJavaVM();

And this is the JAVA Method that I need to call:

public class WebExecute extends Activity{
    public void website(){
        Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"));
        startActivity(browserIntent);
    }
}

Honestly, I am struggling with this, any help is appreciated. Thanks.

Community
  • 1
  • 1
  • What lines do you get errors on now? Just the `JNI_CreateJavaVM` one or others as well? Have you double-checked your compiler/IDE settings to make sure that the `JDK_HOME/include` directory (which contains `jni.h`) is in the includes search path? Same for the `JDK_HOME/include/android` directory (or whatever the operating specific directory in `JDK_HOME/include` is called in a Android JDK)? – QuantumMechanic Jul 04 '12 at 03:52
  • Were you getting a compilation error? – IgorGanapolsky Apr 12 '16 at 17:30

2 Answers2

4

If you are looking at how to call a java method which does not take in any arguments, the format is jmethodID mid = env->GetStaticMethodID(myClass, "myMethod", "()V");

() is how you tell it does not take in any params.

Vsays it returns void. Ljava/lang/String;should be used if the method returns an object of type String.

ben_joseph
  • 1,660
  • 1
  • 19
  • 24
1

A number of things...

  1. Given the declaration JNIEnv* env;, and given that you're in C++, you use it as env->FindClass(someString), not how you're doing it. If it was C you'd use FindClass(env, someString) but in C++ you use env->FindClass(someString).
  2. The string to use in FindClass is the fully qualified path name but with / as the delimiter instead of . For example, if the class is Foo in package bar.baz.quux, the fully-qualified name is bar.baz.quux.Foo and the string you'd give to FindClass is bar/baz/quux/Foo.
  3. You can only create one JVM per C++ process. I'm pretty sure you need to create a single JVM one time. You will therefore need to have the JavaVM* vm be a global variable (or at least be somewhere accessible to everything that needs to use. Everything in the same C++ thread as the thread that called JNI_CreateJavaVM() will use the JNIEnv * that gets filled in by that call. Every other thread that wants to use the JVM needs to call AttachCurrentThread which will bind that thread to the JVM and fill in a new JNIEnv * valid for that thread.
  4. Have you double-checked your compiler/IDE settings to make sure that the JDK_HOME/include directory (which contains jni.h) is in the includes search path? Same for the JDK_HOME/include/android directory (or whatever the operating specific directory in JDK_HOME/include is called in a Android JDK)?

A very useful resource is The JNI book

But be careful while reading it because some examples are in C and some are in C++, so make sure you understand how the calling conventions differ.

QuantumMechanic
  • 13,795
  • 4
  • 45
  • 66
  • I updated my original code above. It still says that JNI_CreateJavaVM is not declared in this scope, even though I have included jni.h. Also, since I do not have a parameter for website(), was I supposed to use NULL as the first parameter of env->CallVoidMethod()? – PRNDL Development Studios Jul 04 '12 at 03:16
  • Some experimentation with `g++` on Linux indicates the `void **` stuff is a red herring (I'm rusty on C++). As I test I declared `void foo(void *)` function and then called it like this: `int i = 42; foo(&i);` and the compiler didn't even give a warning, let alone an error. So I don't think the presence or absence of the `void **` cast is relevant. – QuantumMechanic Jul 04 '12 at 03:47
  • 2
    The `website `method doesn't have parameters so the type signature should be `"()V"` not `"(Ljava/lang/String;)V"` – Driss Bounouar Sep 19 '14 at 10:24