Android系统中的应用程序都是用Java开发的。Android NDK使我们能够在android上使用C/C++开发的原生代码。有两个理由使用NDK: 一是合理的重用现有的代码;二是在程序中某些关键的部分提高执行效率。
这里先讲几个符号的约定:
<project> - 你的Android应用程序工程的目录
<ndk> - 你的ndk安装的目录
捷径
这里先扯一句题外话 -- 如果你不需要使用NDK开发,只是需要使用第三方用NDK开发的库,那么你只需要这样做:
把第三方提供的libxxx.so放到你的<project>/libs/armeabi/下, 然后在程序随便什么地方中加入
static {
System.loadLibray("xxx");
}
就可以使用该库了。
安装NDK
NDK的安装很简单:
1. 首先要将SDK升级至最新,然后下载ndk将它解压到某个目录<ndk>下。
2. 运行: <ndk>/build/host-setup.sh
3. 如果成功的话就OK了,如果失败的话检查一下你是不是下载了正确的ndk版本(例如你的操作系统是linux而下载了windows版的ndk).
Java部分
现在我们用一个很简单的例子来说明NDK的使用。我们在eclipse中新建一个android工程,其中:
Project Name:jnitest
Build Target: Android 1.6
Application Name: JNI Test
Package Name: org.eshock.jnitest
Create Activity: JNITest

JNITest.java:
________________________________________
package org.eshock.jnitest;

import android.app.Activity;
import android.os.Bundle;

public class JNITest extends Activity {
public native int plus (int x, int y);

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int x = plus(1, 2);
android.util.Log.d("jni", String.valueOf(x));
}

static {
System.loadLibrary("mylib");
}
}
________________________________________
我们只是演示NDK,所以就不要界面了。在这个程序中,我们调用一个c语言编写的plus(int, int)函数来计算1+2的值,然后在log中打印它。这个库的名称叫做mylib。
要使用一个c语言的函数,需要在java中声明:
public native int plus(int x, int y);
这样java编译器就知道这个函数是外部库中实现的。
C部分

接下来我们使用C语言实现这个plus函数。
创建<project>/jni/mylib.c:
________________________________________
#include <string.h>
#include <jni.h>

JNIEXPORT jint JNICALL
Java_org_eshock_jnitest_JNITest_plus( JNIEnv* env,
jobject thiz,
jint x,
jint y )
{
return x + y;
}
________________________________________
这 里我们看到,mylib.c里的plus函数比java里面的plus函数的签名要复杂了很多,主要是plus前面增加了包名,函数中多了两个参数,以及 所有的int变成了jint。关于c中类型与jni中类型的对应关系,可以参见jni的相关文档,例如core Java II中的最后一章。如果你不想去查阅文档,有一个方法:
首先随便在某个目录下创建一个文件JNITest.java:
________________________________________
public class JNITest {
public native int plus (int x, int y);
}
________________________________________
然后在命令行下执行:
javac JNITest.java && javah 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: plus
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_JNITest_plus
(JNIEnv *, jobject, jint, jint);

#ifdef __cplusplus
}
#endif
#endif
________________________________________
这里自动生成了java中native函数对应的签名,你可以在c代码中使用它。(记得修改包名)。
Android.mk和Application.mk
Android.mk是一个makefile,用来告诉NDK需要编译哪些文件,生成哪些模块。我们创建<jni>/Android.mk文件:
________________________________________
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := mylib
LOCAL_SRC_FILES := mylib.c

include $(BUILD_SHARED_LIBRARY)
________________________________________
其中LOCAL_PATH表示c源代码文件的位置;LOCAL_MODULE表示生成的共享库的名称;LOCAL_SRC_FILES代表c代码的文件。不需要把头文件列在里面;头文件的依赖关系是ndk自动计算的。

Application.mk的作用是告诉Android SDK需要哪些库文件。有了它,NDK就可以把库放在正确的位置。我们创建<project>/Application.mk:
________________________________________
APP_PROJECT_PATH := $(call my-dir)
APP_MODULES := mylib
________________________________________
APP_PROJECT_PATH代表android工程所在目录,在本例中它被放在<project>中; APP_MODULES表示工程需要的库,如果有多个以空格分开。
编译共享库
由于ndk规定Application.mk必须放在<ndk>/apps/project_name,我们在<ndk>下创建一个符号连接:
ln -s <project> <ndk>/apps/jnitest
这样,我们就可以开始编译共享库了:
在<ndk>目录下运行:
make APP=jnitest
________________________________________
Android NDK: Building for application 'jnitest'
Compile thumb : mylib <= apps/jnitest/jni/mylib.c
SharedLibrary : libmylib.so
Install : libmylib.so => apps/jnitest/libs/armeabi
________________________________________
可以看到编译成功,并在<project>/libs/armeabi/下生成了libmylib.so。
测试
在运行之前,首先确认一下你的工程里面各个文件都齐全,应该类似于这样:


然后测试,正常的话应该能看到log中有输出3.

更多相关文章

  1. [转]Jollen 的 Android(安卓)教學,#4: 使用 XML 安排 UI
  2. Android(安卓)中Ninja 简介
  3. android中SharedPreferences用法详解
  4. Android深入浅出之Zygote
  5. Android(安卓)中 Service 学习,总结
  6. 箭头函数的基础使用
  7. NPM 和webpack 的基础使用
  8. Python技巧匿名函数、回调函数和高阶函数
  9. Python list sort方法的具体使用

随机推荐

  1. Android教学大纲(知识体系结构)
  2. Android中的网络管理源码分析--netd
  3. Android 解压问题(getNextEntry()抛UTFDataF
  4. 《第一行代码--android》笔记·第一章:认
  5. Android连接SQLServer详细教程(数据库+服
  6. android四大组件--ContentProvider详解
  7. Android实现记住用户名和密码功能
  8. Android(安卓)实现个性的ViewPager切换动
  9. 我的android 第31天 - Activity(四)
  10. Android Java包