Eclipse下的Android JNI 开发

jni开发接口头文件的定义很重要,如果频繁的修改上层的接口,一键生成/更新jni头文件就显得尤为快捷.

此头文件是利用javah来生成的(javah来自于JDK),

一.Eclipse->Run->External Tool->External Tool Configurations配置新的external tool javah







测试javah,先选中需要生成jni.h的类,然后执行javah.exe:


没有意外的话随后就能在jni目录下看到对应的头文件了



=============================

1 创建Android工程

首先建立一个名为AndroidJniTest的Android工程,包名默认为com.example.androidjnitest,src目录下自动创建MainActivity.java。

\

2 设计JNI接口

创建新的文件包com.example.jni,并在改包下新建一个TestJNI.java的类。

\

打开TestJNI.java,我们将在这个文件里创建一个JNI接口类,该Java类提供一个加法运算的接口:

?
1
2
3
4
5
public class TestJNI {
public native boolean init();
public native int add( int x , int y);
public native void destory();
}

注意,这里的函数声明要加上native关键字。

3 编译JNI

将TestJNI.java文件复制到工程的bin目录下,在终端中进入该工程的bin目录,输入javac TestJNI.java,这时会生成一个TestJNI.class文件。

\

\

在bin文件夹下,如果没有则创建目录:/com/example/jni,并把TestJNI.class复制到/bin/com/example/jni目录下。然后在终端里进入工程的bin目录,输入javah -jni com.example.jni.TestJNI,此时会生成一个com_example_jni_TestJNI.h文件。<喎�"http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+IDxpbWcgc3JjPQ=="http://www.2cto.com/uploadfile/Collfiles/20150212/2015021208583683.png" alt="\">

com_example_jni_TestJNI.h文件就是对应于上面定义的Java接口的C/C++头文件。打开这个文件,可以看到系统已经为我们自动完成了接口函数的声明:

\

这三个函数分别对应于JNI的三个接口函数,命名方式只是在前面加上了Java包名。

4 用C/C++实现JNI

有了JNI的C/C++头文件,就可以在C层实现JNI接口了。首先在工程目录下创建一个jni目录,这个目录就是专门用来放C/C++代码的。把com_example_jni_TestJNI.h文件复制到jni目录下,并在这里创建一个com_example_jni_TestJNI.cpp文件。

由于我想用C++来实现JNI,所以上面两个文件我只是用来作为动态链接库的接口,具体的实现我希望放在一个类里面来完成,因此我再添加两个文件:Add.h和Add.cpp。

\

下面我们就来实现CAdd类和JNI接口。首先实现CAdd类:

CAdd.h

?
1
2
3
4
5
6
7
8
9
#ifndef JNI_TEST_ADD
#define JNI_TEST_ADD
class CAdd{
public :
CAdd();
~CAdd();
int add( int x, int y);
};
#endif


CAdd.cpp
?
1
2
3
4
5
6
7
8
#include "Add.h"
CAdd::CAdd(){
}
CAdd::~CAdd(){
}
int CAdd::add( int x, int y){
return x+y;
}

然后我们来写com_example_jni_TestJNI.cpp,实现JNI:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdlib.h>
#include <stdio.h>
#include "Add.h"
  
CAdd *pCAdd = NULL;
  
JNIEXPORT jboolean JNICALL Java_com_example_jni_TestJNI_init
   (JNIEnv *env, jobject obj){
if (pCAdd==NULL){
pCAdd = new CAdd ;
}
return pCAdd!=NULL;
}
  
JNIEXPORT jint JNICALL Java_com_example_jni_TestJNI_add
   (JNIEnv *env, jobject obj, jint x, jint y){
jint res = - 1 ;
if (pCAdd!=NULL){
res = pCAdd->add(x,y);
}
return res;
}
  
JNIEXPORT void JNICALL Java_com_example_jni_TestJNI_destory
   (JNIEnv * env, jobject obj){
if (pCAdd!=NULL){
delete pCAdd;
pCAdd=NULL;
}
}</stdio.h></stdlib.h>


到此我们的C/C++部分就全部实现了。

5 创建mk文件

JNI实现了之后就要把C/C++代码编译成动态链接库.so文件,这样Java程序才能调用JNI的接口。要编译so文件,需要写Android.mk和Application.mk两个文件。我们先来写Android.mk。

先在工程目录的jni下创建一个Android.mk文件:

\

然后打开文件在里面输入如下内容:

?
1
2
3
4
5
6
7
8
9
LOCAL_PATH := $(call my-dir)
  
include $(CLEAR_VARS)
  
LOCAL_MODULE    := TestJNI
LOCAL_SRC_FILES := com_example_jni_TestJNI.cpp
LOCAL_SRC_FILES += Add.cpp
  
include $(BUILD_SHARED_LIBRARY)


其中LOCAL_PATH是C/C++代码所在目录,也就是我们的jni目录。

LOCAL_MODULE是要编译的库的名称。编译器会自动在前面加上lib,在后面加上.so。

LOCAL_SRC_FILES是要编译的C/C++文件。

现在我们在工程的根目录下创建一个Application.mk文件,并输入如下内容:

?
1
2
APP_PROJECT_PATH := ${call my-dir}
APP_MODULES := TestJNI

6 编译动态链接库

写完了mk文件就可以开始编译C/C++代码了。

默认在Windows7下配置好了NDK开发环境,打开cygwin,进入到工程目录。

\

在终端里进入工程的根目录,输入命令“$NDK/ndk-build”命令即可编译

\

编译成功后会在工程目录的libs/armeabi目录下生成一个libTestJNI.so文件。

\

7 在Java中调用JNI

现在我们的Android应用可以调用JNI计算加法的代码,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
static {
System.load( "TestJNI" );
}
TextView tvX = null ;
TextView tvY = null ;
TextView tvSum = null ;
Button   btnAdd = null ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvX = (TextView)findViewById(R.id.et_x);
tvY = (TextView)findViewById(R.id.et_y);
tvSum = (TextView)findViewById(R.id.et_sum);
btnAdd = (Button)findViewById(R.id.btn_add);
btnAdd.setOnClickListener( new OnClickListener(){
  
@Override
public void onClick(View v) {
int x = Integer.valueOf( tvX.getText().toString());
int y = Integer.valueOf( tvY.getText().toString());
int sum = 0 ;
TestJNI jni = new TestJNI();
boolean flag = jni.init();
if (flag){
sum = jni.add(x, y);
}
btnAdd.setText(String.valueOf(sum));
}
});
}

程序运行结果:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值