编写最简单的NDK示例
写NDK应用,实际上是写JNI,就是java和本地应用的接口。先看看实现后的效果:
首先需要安装ndk,官方网址:
下载然后解压缩到某个路径下即可。本文环境是mac osx。
设置路径,在以下文件:
vim ~/.bash_profile
设置:
export PATH=${PATH}:/Developer/android-sdk-mac_86/tools:/Developer/android-ndk-r4b
因为mac自带了gcc等开发环境。所以安装十分简单。
下面就是编写ndk项目了。首先编写一个普通的android项目。在activity中,有点儿特殊:
package com.easymorse;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;public class NdkHelloActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView textView = new TextView(this);
setContentView(textView);textView.setText(sayHello());
}public native String sayHello();
static {
System.loadLibrary("helloworld-jni");
}
}
这里的sayHello方法,就是jni需要本地实现的方法,实际上是用c写来实现的。在static块中必须加上对库的加载语句。
jni的写法是自顶向下的,也就是先写java,再生成头文件,然后再写c。好像java先写接口一般。当然c的业务代码可能是写好的,只是差对接jni的部分。
下面生成头文件。需要用到javah命令。
在项目中创建一个jni目录。在命令行下,进入该目录。输入命令:
javah -classpath ../bin com.easymorse.NdkHelloActivity
这里要注意要指向的类不是源文件,而是class文件,而且不是目录结构,是类全名,类似运行class文件。在eclipse adt项目中,class文件在bin目录下。
成功运行后,会在jni目录下生成一个名为 com_easymorse_NdkHelloActivity.h 的头文件:
/* DO NOT EDIT THIS FILE – it is machine generated */
#include <jni.h>
/* Header for class com_easymorse_NdkHelloActivity */#ifndef _Included_com_easymorse_NdkHelloActivity
#define _Included_com_easymorse_NdkHelloActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_easymorse_NdkHelloActivity
* Method: sayHello
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_easymorse_NdkHelloActivity_sayHello
(JNIEnv *, jobject);#ifdef __cplusplus
}
#endif
#endif
这里主要看Java_com_easymorse_NdkHelloActivity_sayHello,这是要在c中实现的方法。
创建c文件,在jni目录下,名为helloword-jni.c:
#include <string.h>
#include <jni.h>jstring JNICALL Java_com_easymorse_NdkHelloActivity_sayHello(JNIEnv* env,
jobject thiz) {
return (*env)->NewStringUTF(env, "你好,世界。来自JNI!");
}
可见实现了上述方法。这里要注意,确保项目的编码是utf-8,否则在运行时会强行退出。
接着,在jni目录下创建一个Android.mk文件,这是构建c的脚本:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := helloworld-jni
LOCAL_SRC_FILES := helloworld-jni.cinclude $(BUILD_SHARED_LIBRARY)
主要是标明编译哪个文件,以及生成so的库名。
倒数第二步,编译生成so文件。命令行,项目根目录下,执行:
ndk-build
会看到根目录下多了一个libs目录。里面的armeabi目录下多了个so文件。
最后一步,在android手机上执行。一般情况下adt环境直接run as 》adnroid application就行了。这里,需要在生成so文件后刷新一下整个adt项目,否则adt会用旧的so文件。
源代码见:
这篇文章上的评论的 RSS feed TrackBack URI