参考资料:
1、版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://eshock.blogbus.com/logs/61459223.html
2、http://www.cnblogs.com/anyanran/archive/2010/11/22/ndk1.html
1、平台及软件信息
通过 uname -a 查看:
Linux ubuntu 3.13.0-35-generic #62-Ubuntu SMP Fri Aug 15 01:58:01 UTC 2014 i686 i686 i686 GNU/Linux
为了确认各环境变量配置正确,可以通过:
java -version 查看:
java version "1.7.0_67" Java(TM) SE Runtime Environment (build 1.7.0_67-b01) Java HotSpot(TM) Client VM (build 24.65-b04, mixed mode)
ndk-build 查看:
Android NDK: Could not find application project directory ! Android NDK: Please define the NDK_PROJECT_PATH variable to point to it. /home/anna/Downloads/android-ndk-r10b/build/core/build-local.mk:148: *** Android NDK: Aborting . Stop.
同时在eclipse中安装好ADT和CDT插件,能正常运行java写的应用程序。
2、编写java代码
新建Android工程,包名设置为”com.anna”,类名为JniTest,在其中实现native方法plus和sayHello,分别用于传回字符串和数字给java。代码如下:
package com.anna; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; public class JniTest extends ActionBarActivity { public native String sayHello(); public native int plus(int x,int y); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_jni_test); int x = plus(3,2); System.out.println("The result in java is: "+x); //将返回的字符串设置为app的title this.setTitle(""+this.sayHello()); } static{ System.loadLibrary("mylib"); } }
3、生成com_anna_JniTest.h头文件
实现native方法需要用javah命令生成相应的头文件,使用头文件中对native方法定义的形式来在C/C++语言中实现,而当前的java代码尚不能使用javac命令正确编译,因此提取出仅包含native方法的Java文件,进行编译获得相关信息。
public class JniTest{ public native String sayHello(); public native int plus(int x,int y); }
使用 javah -jni JniTest 命令生成JniTest.h文件
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class JniTest */ #ifndef _Included_JniTest #define _Included_JniTest #ifdef __cplusplus extern "C" { #endif /* * Class: JniTest * Method: sayHello * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_JniTest_sayHello (JNIEnv *, jobject); /* * Class: JniTest * Method: plus * Signature: (II)I */ JNIEXPORT jint JNICALL Java_JniTest_plus (JNIEnv *, jobject, jint, jint); #ifdef __cplusplus } #endif #endif
其中的两个JNIEXPORT句就是所需要的native方法描述,切记要在函数名之前添加包名,即Java_JniTest_sayHello ——> Java_com_anna_JniTest_sayHello
4、编写.c文件
在路径下新建名为jni的文件夹,在其中新建mylib.c(根据System.loadLibrary("mylib");命名),内容为:
#include <string.h> #include <jni.h> JNIEXPORT jint JNICALL Java_com_anna_JniTest_plus(JNIEnv *env, jobject obj, jint x, jint y) { return x+y; } JNIEXPORT jstring JNICALL Java_com_anna_JniTest_sayHello(JNIEnv *env, jobject obj){ return (*env)->NewStringUTF(env, "Hello from JNI ! "); }
在其中实现了int型和String类型数据的返回,C和java中数据类型并不完全对应,因此使用jint、jstring样式的命名方式方便编程。
5、编写Android.mk和Application.mk文件
在jni文件夹下新建文件Android.mk,内容如下:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := mylib LOCAL_SRC_FILES := mylib.c include $(BUILD_SHARED_LIBRARY)
其中LOCAL_MODULE表示要生成的动态链接库.so文件的文件名(所生成的文件会自动添加lib头,即本次生成的so文件名为”libmylib.so”),LOCAL_SRC_FILES表示c文件的所在路径。
在项目总目录下(即与src目录等同级)新建文件Application.mk,内容如下:
APP_PROJECT_PATH := $(call my-dir) APP_MODULES := mylib
其中的APP_MODULES与LOCAL_SRC_FILES的内容相同。
6、生成libmylib.so文件
切换命令行工具到jni目录下,使用 -ls 命令查看,文件夹内包含:
Android.mk mylib.c
之后使用 ndk-build 命令,运行后命令行输出如下:
[armeabi] Install : libmylib.so => libs/armeabi/libmylib.so
根据输出可知,输出的so文件存放在整个项目的ibs/armeabi/路径下,如果没有的话,右键工程”refresh”一下就出现啦。
7、运行工程,查看输出结果
LogCat中输出结果为:
模拟器界面输出为:
(注:Hello World是工程默认建立的TextView……)