您的位置:首页 > 移动开发 > Android开发

android jni 使用方法

2013-05-03 14:48 489 查看

AndroidJNI使用方法

您的评价:收藏该经验
经过几天的努力终于搞定了androidJNI部分,下面将我的这个小程序和大家分享一下。androidJNI是连接androidJava部分和C/C++部分的纽带,完整使用JNI需要Java代码和C/C++代码。其中C/C++代码用于生成库文件,Java代码用于引用C/C++库文件以及调用C/C++方法。

androidJava部分代码:

01
jnitest.java
02
03
package
com.hello.jnitest;
04
05
06
07
import
android.app.Activity;
08
09
import
android.os.Bundle;
10
11
12
13
public
class
jnitest
extends
Activity
{
14
15
/**
Calledwhentheactivityisfirstcreated.*/
16
17
@Override
18
19
public
void
onCreate(Bundle
savedInstanceState){
20
21
super
.onCreate(savedInstanceState);
22
23
setContentView(R.layout.main);
24
25
Nadd
test=
new
Nadd();
26
27
setTitle(
"The
NativeAddResultis"
+String.valueOf(test.nadd(
10
,
20
)));
28
29
}
30
31
}
32
33
Nadd.java
34
35
package
com.hello.jnitest;
36
37
38
39
public
class
Nadd
{
40
41
static
{
42
43
System.loadLibrary(
"hello_jni"
);
44
45
}
46
47
48
49
public
native
int
nadd(
int
a,
int
b);
50
51
}
Java代码说明:
1)jnitest.java是一个activity的类对象,在该类对象中生成调用JNI函数的类对象,同时调用JNI方法,最后将JNI方法的结果显示到标题栏上;
2)Nadd.java是一个引用和声明JNI库和函数的类,其中System.loadLibrary();函数用来引用JNI库,默认JNI库放在android系统的/system/lib/目录下;publicnaddintnadd(inta,intb);为声明需要在java程序中使用的JNI库中的函数;
JNI中java部分的代码到此就结束了,总结一下在java代码中需要做两件事:
1)使用System.loadLibrary()函数来引用JNI库;
2)声明调用JNI库的函数且前面添加native关键字;

androidC/C++部分代码:

01
#define
LOG_TAG"hello-JNI"
02
#include
<stdio.h>
03
#include
<stdlib.h>
04
#include
<unistd.h>
05
#include
<sys/types.h>
06
#include
<sys/stat.h>
07
#include
<fcntl.h>
08
#include
<assert.h>
09
#include
"jni.h"
10
#include
"JNIHelp.h"
11
#include
"android_runtime/AndroidRuntime.h"
12
static
jint
com_hello_jnitest_jnitest_nadd(JNIEnv*env,jobjectobj,jinta,jintb)
13
{
14
return
(a
*b);
15
}
16
static
JNINativeMethod
gMethods[]={
17
{
"nadd"
,
"(II)I"
,
(
void
*)com_hello_jnitest_jnitest_nadd},
18
};
19
static
int
register_android_test_hello(JNIEnv
*env)
20
{
21
return
android::AndroidRuntime::registerNativeMethods(env,
"com/hello/jnitest/Nadd"
,
gMethods,NELEM(gMethods));
22
}
23
jint
JNI_OnLoad(JavaVM*vm,
void
*reserved)
24
{
25
JNIEnv
*env=NULL;
26
if
(vm->GetEnv((
void
**)&env,
JNI_VERSION_1_4)!=JNI_OK){
27
printf
(
"Error
GetEnv\n"
);
28
return
-1;
29
}
30
assert
(env
!=NULL);
31
if
(register_android_test_hello(env)
<0){
32
printf
(
"register_android_test_hello
error.\n"
);
33
return
-1;
34
}
35
return
JNI_VERSION_1_4;
36
}
JNIC/C++代码说明:
1)JNI_OnLoad()函数。该函数在Java程序调用System.loadLibrary()时,被调用执行,用于向JavaVM注册JNI函数等。在本例中首先通过参数JavaVM(Java虚拟机指针)获取当前应用程序所在的线程,即:JNIEnv。再通过调用android::AndroidRuntime::registerNativeMethods()注册native实现的函数指针。
2)JNI函数和Java调用函数的映射关系。使用JNINativeMethod将java调用的函数名与JNI实现的函数名联系在一起;
3)JNI函数实现;

Android.mk代码:

1
LOCAL_PATH
:=$(callmy-dir)
2
include
$(CLEAR_VARS)
3
LOCAL_PRELINK_MODULE
:=
false
4
LOCAL_SRC_FILES
:=\
5
com_hello_jnitest.cpp
6
LOCAL_SHARED_LIBRARIES
:=\
7
libandroid_runtime
8
LOCAL_MODULE
:=libhello_jni
9
include
$(BUILD_SHARED_LIBRARY)
需要注意的是:
1)JNIC/C++部分的代码需要在android源代码树上进行编译,编译完成后我的做法是直接将生成的.so通过adbpush方法上传到android虚拟机的/system/lib/目录下;
2)java代码可以在eclipse下直接编译且在虚拟机上执行;

编译JNIC/C++部分代码(在android内核源代码根目录下):
#makelibhello_jni
之后在out/target/product/generic/system/lib/目录下生成libhello_jni.so

上传libhello_jni.so到android虚拟机:
#adbpushout/target/product/generic/system/lib/libhello_jni.so/system/lib
注意:此时有可能出现OutofMemory的错误提示。当出现如上错误提示时,需要使用#adbremount重新加载一下就可以了。
另外,也有可能直接使用eclipse启动android虚拟机时出现上述错误且使用#adbremount也出现的情况,此时需要手动启动android虚拟机,如:#emulator-avdxxx-partition-size128,之后在使用#adbpush就可以了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: