编写最简单的NDK示例

写NDK应用,实际上是写JNI,就是java和本地应用的接口。先看看实现后的效果:

image

首先需要安装ndk,官方网址:

http://androidappdocs.appspot.com/sdk/ndk/index.html

下载然后解压缩到某个路径下即可。本文环境是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.c

include $(BUILD_SHARED_LIBRARY)

 

主要是标明编译哪个文件,以及生成so的库名。

倒数第二步,编译生成so文件。命令行,项目根目录下,执行:

ndk-build

会看到根目录下多了一个libs目录。里面的armeabi目录下多了个so文件。

最后一步,在android手机上执行。一般情况下adt环境直接run as 》adnroid application就行了。这里,需要在生成so文件后刷新一下整个adt项目,否则adt会用旧的so文件。

源代码见:

http://easymorse.googlecode.com/svn/trunk/ndk.hello/

PDF下載    发送文章为PDF   

这篇文章上的评论的 RSS feed TrackBack URI

Leave a Reply