How to call Java from C on Android ?

3,836 views
Skip to first unread message

Danny Backx

unread,
May 20, 2010, 4:31:13 PM5/20/10
to andro...@googlegroups.com
Hi,

I need to be able to call Java from C code, and I have trouble getting
this to work in my sample program. Help :-)

Relevant code below. I tried with GetStaticMethodID +
CallStaticVoidMethod but that didn't work either (GetStaticMethodID
returns 0).

Also I'm not sure why this business with env vs lenv is happening. Code
was created by copying stuff from forum posts...

Danny

E/Yow ( 711): DoubleJniTest 1
E/Yow ( 711): DoubleJniTest NewStringUTF -> 0x43d114a0
E/Yow ( 711): DoubleJniTest GetObjectClass -> 0x43cffd00
E/Yow ( 711): DoubleJniTest GetStaticMethodID -> 0x412be468
I/DEBUG ( 27): *** *** *** *** *** *** *** *** *** *** *** *** ***
*** *** ***
I/DEBUG ( 27): Build fingerprint:
'generic/sdk/generic/:2.1/ERD79/22607:eng/test-keys'
I/DEBUG ( 27): pid: 711, tid: 711 >>>
net.sourceforge.projects.roadmap <<<
I/DEBUG ( 27): signal 11 (SIGSEGV), fault addr 00000004
I/DEBUG ( 27): r0 4104f100 r1 00000000 r2 40009408 r3 ad07ff50


<<RoadMap.java>>
package net.sourceforge.projects.roadmap;
...
public class RoadMap extends Activity
...
public void AddButton(String name) {
Button doit = new Button(thiz);

doit.setText(name);
buttons.addView(doit);
}

<< piece of jni/jni.c >>
static JavaVM *svm;
static jobject io;

jint
JNI_OnLoad(JavaVM *vm, void *reserved)
{
JNIEnv *env;
jclass cls;
jmethodID constr;

svm = vm;
if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6) != JNI_OK)
return -1;
cls = (*env)->FindClass(env,
"net/sourceforge/projects/roadmap/RoadMap");
__android_log_print(ANDROID_LOG_ERROR, "JNI_OnLoad", "FindClass
-> %p", cls);
constr = (*env)->GetMethodID(env, cls, "<init>", "()V");
__android_log_print(ANDROID_LOG_ERROR, "JNI_OnLoad",
"GetMethodID -> %p", constr);
io = (*env)->NewGlobalRef(env, (*env)->NewObject(env, cls,
constr));
__android_log_print(ANDROID_LOG_ERROR, "JNI_OnLoad", "io -> %p",
io);

return JNI_VERSION_1_6;
}

void
JNI_OnUnload(JavaVM *vm, void *reserved)
{
JNIEnv *env;

(*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6);
(*env)->DeleteGlobalRef(env, io);
}

void
Java_net_sourceforge_projects_roadmap_RoadMap_DoubleJniTest(JNIEnv* env,
jobject thiz, char *s)
{
JNIEnv *lenv;
jclass c;
jmethodID m;
char * ns;

__android_log_print(ANDROID_LOG_ERROR, "Yow", "DoubleJniTest
1");

if ((*svm)->GetEnv(svm, (void **)&lenv, JNI_VERSION_1_6) < 0) {
__android_log_print(ANDROID_LOG_ERROR, "Yow",
"DoubleJniTest error");
return;
}

ns = (*lenv)->NewStringUTF(lenv, "Yow baby");
__android_log_print(ANDROID_LOG_ERROR, "Yow", "DoubleJniTest
NewStringUTF -> %p", ns);

c = (*lenv)->GetObjectClass(lenv, io);
__android_log_print(ANDROID_LOG_ERROR, "Yow", "DoubleJniTest
GetObjectClass -> %p", c);
m = (*env)->GetMethodID(env, c, "AddButton",
"(Ljava/lang/String;)V");
__android_log_print(ANDROID_LOG_ERROR, "Yow", "DoubleJniTest
GetStaticMethodID -> %p", m);
(*env)->CallVoidMethod(env, c, m, ns);

__android_log_print(ANDROID_LOG_ERROR, "Yow", "DoubleJniTest
4");

}


--
Danny Backx ; danny.backx - at - scarlet.be ; http://danny.backx.info

--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To post to this group, send email to andro...@googlegroups.com.
To unsubscribe from this group, send email to android-ndk...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/android-ndk?hl=en.

laurent mallet

unread,
May 20, 2010, 4:34:02 PM5/20/10
to android-ndk
I recommand to look source code of kwaak. You will find many
interesting code.

http://code.google.com/p/kwaak3/

Laurent,

fadden

unread,
May 20, 2010, 6:52:00 PM5/20/10
to android-ndk
On May 20, 1:31 pm, Danny Backx <danny.ba...@scarlet.be> wrote:
> Relevant code below. I tried with GetStaticMethodID +
> CallStaticVoidMethod but that didn't work either (GetStaticMethodID
> returns 0).

Don't use GetStaticMethodID on a non-static method.


> void
> Java_net_sourceforge_projects_roadmap_RoadMap_DoubleJniTest(JNIEnv* env,
> jobject thiz, char *s)
> {
[...]
>         if ((*svm)->GetEnv(svm, (void **)&lenv, JNI_VERSION_1_6) < 0) {

You have an "env", passed in. You don't need to query for it.


>         c = (*lenv)->GetObjectClass(lenv, io);
[...]
>         (*env)->CallVoidMethod(env, c, m, ns);

The second argument is the instance of the object on which you are
calling the method. You're passing in a class object. This is not
going to work.

It looks like you want to CallVoidMethod(env, io, m, ns). Note "ns"
is a jstring, not a char*.

Danny Backx

unread,
May 21, 2010, 6:00:40 PM5/21/10
to andro...@googlegroups.com
Thanks for both replies, I got things to work now, see below.

Danny

void
Java_net_sourceforge_projects_roadmap_RoadMap_DoubleJniTest(JNIEnv* env,
jobject thiz, char *s)
{
jclass cls;
jmethodID mid;
int i;
jstring js;

cls = (*env)->FindClass(env,
"net/sourceforge/projects/roadmap/RoadMap");
if (cls == 0)
return;

mid = (*env)->GetMethodID(env, cls, "AddDummyButton", "(I)I");
if (mid == 0)
return;
i = (*env)->CallIntMethod(env, thiz, mid, 5);

js = (*env)->NewStringUTF(env, "yow");

mid = (*env)->GetMethodID(env, cls, "AddButton",
"(Ljava/lang/String;)V");
if (mid == 0)
return;
(*env)->CallVoidMethod(env, thiz, mid, js);
}


public void AddButton(String name) {
Button doit = new Button(thiz);
doit.setText(name);
buttons.addView(doit);
}

public int AddDummyButton(int a) {
Button doit = new Button(thiz);
buttons.addView(doit);
return 123;
}


--
Danny Backx ; danny.backx - at - scarlet.be ; http://danny.backx.info

siva

unread,
Jul 6, 2011, 6:27:49 AM7/6/11
to andro...@googlegroups.com

Hi,
Nice explanation, but still i've confusion. So I request you to send me the
complete code of RoadMap.java and jni.c.

Can you please post here??


siva prasad reddy

unread,
Jul 6, 2011, 8:04:26 AM7/6/11
to android-ndk
Hi Everybody!!
I need to be able to call Java from C code, and I have trouble getting
this to work in my sample program. I'm getting blank screen..Help :-)

Relevant code below.
RoadMap.java
--------------------------------------------------------------------------------------------
public class RoadMap extends Activity
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//AddButton("Hello");
this.DoubleJniTest();

}

public void AddButton(String name) {
LinearLayout buttons = (LinearLayout) findViewById(R.id.container);
Button doit = new Button(this);
doit.setText(name);
buttons.addView(doit);
System.out.println("------------- Add buttons..");
}
/*public int AddDummyButton(int a) {
LinearLayout buttons = (LinearLayout) findViewById(R.id.container);
Button doit = new Button(this);
buttons.addView(doit);
return 123;
}*/
public native void DoubleJniTest();
static
{
System.loadLibrary("jni");
}
}
//----------------------------------------------------------------------------------------------------------------------------
jni.c

#include <jni.h>
#include <android/log.h>
#include "com_example_roadmap_RoadMap.h"

static JavaVM *svm;
static jobject io;
jint
JNI_OnLoad(JavaVM *vm, void *reserved)
{
JNIEnv *env;
jclass cls;
jmethodID constr;
svm = vm;
if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6) !=
JNI_OK)
return -1;
cls = (*env)->FindClass(env, "com/examples/roadmap/RoadMap");
__android_log_print(ANDROID_LOG_ERROR, "JNI_OnLoad",
"FindClass-> %p", cls);
constr = (*env)->GetMethodID(env, cls, "<init>", "()V");
__android_log_print(ANDROID_LOG_ERROR, "JNI_OnLoad",
"GetMethodID -> %p", constr);
io = (*env)->NewGlobalRef(env, (*env)->NewObject(env, cls,
constr));
__android_log_print(ANDROID_LOG_ERROR, "JNI_OnLoad", "io ->
%p", io);
return JNI_VERSION_1_6;
}

void
JNI_OnUnload(JavaVM *vm, void *reserved)
{
JNIEnv *env;
(*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6);
(*env)->DeleteGlobalRef(env, io);
}
void
Java_com_examples_roadmap_RoadMap_DoubleJniTest(JNIEnv* env, jobject
thiz)
{
jclass cls;
jmethodID mid;
int i;
jstring js;
cls = (*env)->FindClass(env,"com/examples/roadmap/RoadMap");
if (cls == 0)
return;
/**mid = (*env)->GetMethodID(env, cls, "AddDummyButton",
"(I)I");
if (mid == 0)
return;
i = (*env)->CallIntMethod(env, thiz, mid, 5); */
js = (*env)->NewStringUTF(env, "Got It!");
mid = (*env)->GetMethodID(env, cls, "AddButton", "(Ljava/lang/
String;)V");
if (mid == 0)
return;
(*env)->CallVoidMethod(env, thiz, mid, js);
}
//-------------------------------------------------------------------------------------------------------------------------
main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/
android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/container"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
</LinearLayout>







Christopher Van Kirk

unread,
Jul 6, 2011, 11:17:09 PM7/6/11
to andro...@googlegroups.com
Did you try the methods one might use to call from native into Java on any
other platform?

}

--


You received this message because you are subscribed to the Google Groups
"android-ndk" group.
To post to this group, send email to andro...@googlegroups.com.
To unsubscribe from this group, send email to
android-ndk...@googlegroups.com.
For more options, visit this group at
http://groups.google.com/group/android-ndk?hl=en.

-----
No virus found in this message.
Checked by AVG - www.avg.com
Version: 10.0.1388 / Virus Database: 1516/3734 - Release Date: 06/29/11
Internal Virus Database is out of date.

siva prasad reddy

unread,
Jul 7, 2011, 12:24:11 AM7/7/11
to andro...@googlegroups.com
I've tried on Android Platform. Now i'm able to run.

Thanks for  your reply!!
Regards
-------------
Siva Prasad Reddy S,
Associate Software Engineer - Trainee,
ArijaSoft,
Hyderabad.



Sarker Tanveer Ahmed Rumee

unread,
Aug 9, 2014, 12:47:47 AM8/9/14
to andro...@googlegroups.com
Could you please help regarding how you did it Android?
Reply all
Reply to author
Forward
0 new messages