Linux下通过NDK的初步使用【详细步骤+截图】
参考资料:
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……)