转自:http://eshock.blogbus.com/logs/61459223.html
前言
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>下。
其实,下载地址没有被和谐,输入
http://dl.google.com/android/ndk/xxxx.zip是可以直接下载的
用在线代理看下到 http://developer.android.com/sdk/ndk/
最新的版本,例如:
[转]Android NDK学习笔记_第1张图片
把xxxx替换成图中的版本号:
http://dl.google.com/android/ndk/android-ndk-r4b-linux-x86.zip
直接下载即可

2. 运行: <ndk>/build/host-setup.sh
这步已经不必要了
However, this step has been removed in release 4 (a.k.a. r4).

3. 把<ndk>加入到环境变量中,然后到<ndk>/samples/hello-jni/下运行ndk-build,看能否生成
libhello-jni.so

4. 如果成功的话就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 JNICALLJava_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 __cplusplusextern "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    := mylibLOCAL_SRC_FILES := mylib.cinclude $(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。
测试
在运行之前,首先确认一下你的工程里面各个文件都齐全,应该类似于这样:
[转]Android NDK学习笔记_第2张图片

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

更多相关文章

  1. C语言函数以及函数的使用
  2. 诚聘Android开发工程师
  3. Android 文件格式
  4. android项目中每个文件的作用
  5. Fast File Transfer – 让 Android 通过 WIFI 传输文件到任何无
  6. Android开发5——文件读写
  7. Android布局文件属性笔记
  8. adb设备连接以及文件拷贝

随机推荐

  1. Android Studio解决Java程序输出中文乱码
  2. 字符串与字典之间的相互转换-Python
  3. android中自定义组件
  4. Android 绘图中的抗锯齿处理
  5. Context.startForegroundService() did n
  6. Android Opencore PVPlayer
  7. Android 岗位 应聘所需 技能
  8. android Uri利用及解析(文件操作)以及与路
  9. Android 选项卡效果
  10. Android studio 混淆打包 proguard-rules