作者:郭明宇

什么是Android NDK

Android 应用程序是运行在Dalvik虚拟机之上的。NDK可以让你用本地代码例如C/C++来实现应用程序的一部分。这样可以为应用程序的某些类在复用已有代码或提高性能方面提供便利。

如果你的代码是用C/C++来实现的,你的应用程序仍然会被打包成.apk文件,并且仍然运行在虚拟机上。Android应用程序的模型是不变的。


NDK的下载及安装

NDK的官方下载地址为:

http://developer.android.com/sdk/ndk/index.html

下载完成后进行解压,就可以直接使用目录中的ndk-build了。为了使用方便,可以用如下命令将ndk-build放入默认路径中:

exportPATH=$PATH:<你解压好的目录地址>


NDK的使用方法

目前为止,用C/C++编写Android应用程序有两种方式:

1. C/C++编写主要的逻辑层,再用java编写界面层并调用C/C++的库;

2. C/C++直接开发完整的应用程序,完全不用java(Android 2.3之后的版本支持)

第一种方法较为通用,因为用java开发Android应用程序的界面比较简单;第二种方法较为复杂并且很少用到。在此我们只介绍第一种使用方法的步骤,第二种使用方法可以在第一种方法的基础上,参照NDK目录中自带的例子程序samples/native-activity

我们以一个简单的例子,一步步带领大家写出一个简单的hello-jni程序。

第一步建立一个Android工程

如果你使用eclipse进行开发,很简单,在此就不赘述了。不过为了与下文的名称保持一致,请把项目名设为hello-jni,包名为com.example.hellojni,类名为HelloJni

如果你使用shell进行开发,执行如下三行命令即可:

mkdirhello-jni

cdhello-jni

androidcreate project -p . -t android-8 -k com.example.hellojni -a HelloJni

第二步编写C源文件及Makefile

在项目目录下新建一个jni目录,然后在jni目录下建立两个文件:

第一个:main.c文件,内容如下:

#include<string.h>

#include<jni.h>

 

/*This is a trivial JNI example where we use a native method

 * toreturn a new VM String. See the corresponding Java source

 * filelocated at:

 *

 *   hello-jni/src/com/example/HelloJni/HelloJni.java

 */

jstring

Java_com_example_hellojni_HelloJni_stringFromJNI(JNIEnv* env,

                                                 jobject thiz )

{

    return(*env)->NewStringUTF(env, "Hello from JNI !");

}

第二个:Android.mk文件,内容如下:

LOCAL_PATH:= $(call my-dir)

 

include$(CLEAR_VARS)

 

LOCAL_MODULE    := hello-jni

LOCAL_SRC_FILES:= hello-jni.c

 

include$(BUILD_SHARED_LIBRARY)

第三步编译C源码生成so文件

直接在hello-jni目录下执行ndk-build。如果编译成功,可以看到生成了libs/armeabi/libhello-jni.so文件,该文件就是我们得到的C库了。

第四步java源码中调用C库中的函数

hello-jni下打开src/com/example/jni/HelloJni.java文件,可以看到Android SDK已经帮我们自动生成了一些代码:

packagecom.example.jni;

 

importandroid.app.Activity;

importandroid.os.Bundle;

 

publicclass HelloJni extends Activity

{

    /**Called when the activity is first created. */

    @Override

    publicvoid onCreate(Bundle savedInstanceState)

    {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

    }

}

为了调用我们用C写好的函数,需要对其进行简单修改,修改后内容如下:

packagecom.example.hellojni;

 

importandroid.app.Activity;

importandroid.widget.TextView;

importandroid.os.Bundle;

 

 

publicclass HelloJni extends Activity

{

    /**Called when the activity is first created. */

    @Override

    publicvoid onCreate(Bundle savedInstanceState)

    {

        super.onCreate(savedInstanceState);

 

        TextView  tv = new TextView(this);

        tv.setText(stringFromJNI() );

        setContentView(tv);

    }

 

    publicnative String  stringFromJNI();

 

    static{

        System.loadLibrary("hello-jni");

    }

}

                                              

对比两个文件可以看到需要修改的几个地方:

1. 引入了一个TextView

TextView  tv = new TextView(this);

2. 在末尾,我们在static域内调用了:

System.loadLibrary("hello-jni");

这个调用的目的就是引入刚刚编译好的那个C库,这个C库的名字就叫hello-jni,这个名字是我们在Android.mk文件中指定的:

LOCAL_MODULE    := hello-jni

这两处的名称需要保持一致。

3. 我们声明了一个函数

publicnative String  stringFromJNI();

并在TextView中调用了它,将其返回结果显示出来

tv.setText(stringFromJNI() );

这个函数定义的地方,就是我们在刚刚C文件中写道的

jstring

Java_com_example_hellojni_HelloJni_stringFromJNI(JNIEnv* env,

                                                  jobject thiz )

{

    return(*env)->NewStringUTF(env, "Hello from JNI !");

}

有人会问这两个函数的名称为什么不一样,有什么对应关系。没错,是不同。对应关系是

C中定义的名称为:Java_包名_类名_函数名

java中调用的名称为:函数名

第四步编译生成apk文件

如果你使用eclipse进行开发,点击编译运行就可以了。

如果你使用shell进行开发,输入命令:

antdebug

bin下就得到了HelloJni-debug.apk,用adb install即可进行安装了。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐