本文实现在Android app中使用调用jni库调用本地C/C++方法。

1.新建android工程

2.新建java上层方法

本例子在工程中新建 cn.landsem.jnistudy 包,在其中新建TestManager类用于调用本地C/C++方法,该类的代码如下:


1. package cn.landsem.jnistudy;  
2.   
3. import android.util.Log;  
4.   
5. public class TestManager {  
6. public static String TAG = "TestManager";  
7. static {  
8. try {    
9. "lstest");    
10. catch (Exception e) {  
11.             e.printStackTrace();  
12.             Log.d(TAG,e.getMessage());  
13.         }         
14. "native_init");  
15.         nativeInit();  
16.     }  
17.       
18. public int add(int i,int j) {  
19. "add");  
20. return nativeAdd(i,j);  
21.     }  
22.   
23. private static native void nativeInit();  
24. private static native int nativeAdd(int i,int j);  
25. }

3.创建jni头文件

打开dos命令窗口,切换到工程目录下的“bin\classes”目录,输入javah -jni cn.landsem.jnistudy.TestManager命令,命令执行成功后会在该目录下生成对应的jni头文件,如本文中完成上述命令会生成 cn_landsem_jnistudy_TestManager.h 文件,文件内容如下:


1. /* DO NOT EDIT THIS FILE - it is machine generated */  
2. #include <jni.h>  
3. /* Header for class cn_landsem_jnistudy_TestManager */  
4.   
5. #ifndef _Included_cn_landsem_jnistudy_TestManager  
6. #define _Included_cn_landsem_jnistudy_TestManager  
7. #ifdef __cplusplus  
8. extern "C" {  
9. #endif  
10. /*
11.  * Class:     cn_landsem_jnistudy_TestManager
12.  * Method:    nativeInit
13.  * Signature: ()V
14.  */  
15. JNIEXPORT void JNICALL Java_cn_landsem_jnistudy_TestManager_nativeInit(JNIEnv *, jclass);  
16.   
17. /*
18.  * Class:     cn_landsem_jnistudy_TestManager
19.  * Method:    nativeAdd
20.  * Signature: (II)I
21.  */  
22. JNIEXPORT jint JNICALL Java_cn_landsem_jnistudy_TestManager_nativeAdd(JNIEnv *, jclass, jint, jint);  
23.   
24. #ifdef __cplusplus  
25. }  
26. #endif  
27. #endif


4.新建jni实现

在工程中新建jni目录,将上部操作中生成的jni头文件拷贝到该目录,新建一个c++源文件实现jni中定义的方法,如本文在jni目录下新建cn_landsem_jnistudy_TestManager.cpp文件用于实现上述方法,该方法实现代码如下:


1. #include "android_runtime/AndroidRuntime.h"  
2. #include "JNIHelp.h"  
3. #include "jni.h"  
4. #include "utils/Log.h"  
5. #include "utils/misc.h"  
6. #include "cn_landsem_jnistudy_TestManager.h"  
7. #include <android/log.h>   
8. #include <stdio.h>  
9. #include <string.h>  
10. #include <stdlib.h>  
11. #include <errno.h>  
12. #include <unistd.h>  
13. #include <sys/types.h>  
14.   
15. #define LOG_TAG "Test_JNI"  
16.   
17. JNIEXPORT void JNICALL Java_cn_landsem_jnistudy_TestManager_nativeInit  
18.   (JNIEnv *, jclass)  {  
19. "call Java_cn_landsem_jnistudy_TestManager_nativeInit");  
20. }  
21.   
22. /*
23.  * Class:     cn_landsem_jnistudy_TestManager
24.  * Method:    native_add
25.  * Signature: (II)I
26.  */  
27. JNIEXPORT jint JNICALL Java_cn_landsem_jnistudy_TestManager_nativeAdd  
28.   (JNIEnv *, jclass, jint, jint) {  
29. "call Java_cn_landsem_jnistudy_TestManager_nativeAdd");  
30. return 0;  
31. }


5、生成jni so库

在jni目录下新建Android.mk文件用于编译生成jni库,该文件内容如下:


1. # Copyright (C) 2010 The Android Open Source Project  
2. #  
3. # Licensed under the Apache License, Version 2.0 (the "License");  
4. # you may not use this file except in compliance with the License.  
5. # You may obtain a copy of the License at  
6. #  
7. #      http://www.apache.org/licenses/LICENSE-2.0  
8. #  
9. # Unless required by applicable law or agreed to in writing, software  
10. # distributed under the License is distributed on an "AS IS" BASIS,  
11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
12. # See the License for the specific language governing permissions and  
13. # limitations under the License.  
14.   
15. LOCAL_PATH:= $(call my-dir)  
16.   
17. include $(CLEAR_VARS)  
18. LOCAL_SRC_FILES := cn_landsem_jnistudy_TestManager.cpp  
19.   
20. LOCAL_SHARED_LIBRARIES := \  
21.     libcutils \  
22.     libutils \  
23.     liblog  \  
24.   
25. LOCAL_MODULE:= liblstest  
26.   
27. include $(BUILD_SHARED_LIBRARY)


6、包含jni库到工程中

在工程libs目录下新建armeabi目录和armeabi-v7a目录,将生成的jni库放到该目录下。

7、调用

在工程中调用 TestManager 类即可测试。

8、源码下载

工程导入后会出错

具体错误在budild.gradle中、

修改 android 下

compileSdkVersion 19

    sourceSets.main {
        jni.srcDirs = []
        jniLibs.srcDir 'src/main/libs'
    }