前言

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.

转载于:https://www.cnblogs.com/qq78292959/archive/2011/11/02/2232880.html

Android NDK学习笔记(转)相关推荐

  1. Android NDK学习笔记1:基础

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/119005718 本文出自[赵彦军的博客] 文章目录 (一)什么是Android N ...

  2. Android NDK学习笔记6:异常处理

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/119547007 本文出自[赵彦军的博客] 文章目录 JNI捕获异常 JNI抛出异常 ...

  3. Android NDK学习笔记3:JNI访问Java属性、方法

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/119209444 本文出自[赵彦军的博客] 文章目录 Java 类型和JNI符号对比 ...

  4. Android NDK学习笔记5:引用类型管理

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/119545225 本文出自[赵彦军的博客] 文章目录 局部引用 全局引用 弱引用 总 ...

  5. Android NDK学习笔记4:JNI访问Java构造函数

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/119348263 本文出自[赵彦军的博客] 文章目录 方式一:NewObject 方 ...

  6. Android NDK学习笔记2:数组

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/119152933 本文出自[赵彦军的博客] 文章目录 java数组和jni数组对应关 ...

  7. Android 开发学习笔记:七大知识点板块汇总

    前言 我从事 Android 开发行业也有些年头,工作期间也接触过很多 Android 开发者, 因此也非常清楚 程序员最大的限制并非年龄而是实力: 但大多数初中级Android工程师,想要提升技能, ...

  8. NDK学习笔记:JNI调用Java层方法创建Native的AudioTrack播放PCM(方法签名,CallXXXMethod)

    NDK学习笔记:JNI调用Java层方法创建Native的AudioTrack播放PCM 题目有点复杂,不过确实就是那么回事.这章想记录的内容比较多,先列出来: native static 与 nat ...

  9. NDK学习笔记:FFmpeg音视频同步3(你追我赶,升级ffmpeg/libyuv支持neon)

    NDK学习笔记:FFmpeg音视频同步3 本篇内容说多不多,但如果要说得明明白白的,可能就有点难度了.所以我决定把我的调试过程日志都呈现出来,方便大家理解.继上一篇文末,我们学习到了什么是DTS/PT ...

最新文章

  1. SQLServer查看存储过程的方法
  2. R语言colSums函数、rowSums函数、colMeans函数、rowMeans函数、colMedians函数、rowMedians计算dataframe行或者列的加和、均值、中位数实战
  3. mysql将字符转换成数字
  4. Linux内核之于红黑树and AVL树
  5. insert批量插入500ms_如何快速安全的插入千万条数据
  6. 汇编语言随笔(10)-内中断及实验12(返回到dos的中断处理程序)
  7. linux脚本的数据输出到excel,使用shell实现Excel表格导出功能 | 剑花烟雨江南
  8. stm32 交换机芯片_基于STM32的全链路语音交互 - stm32/stm8 - 电子工程世界
  9. java 断点续传组件_chunkupload 文件上传断点续传组件(java) - 正式发布
  10. python网络爬虫文献综述怎么写_毕业论文的文献综述怎么写
  11. [ZZ]Debug VBScript with Visual Studio
  12. 程序包清单签名验证失败_数字世界的手写签名
  13. yum下载文件的缓存位置
  14. QBC的distinct查询
  15. ICC_lab总结——ICC_lab3:布局
  16. 剑指offer题目大全
  17. 机器学习模型评价(Evaluating Machine Learning Models)-主要概念与陷阱
  18. android 状态栏显示 耳机图标显示,Android4.0-4.4 加入支持状态栏显示耳机图标方法(支持带不带MIC的两种耳机自己主动识别)...
  19. New Online Judge P1128-绝地求生(多源bfs)
  20. 对未来“机器学习”的看法

热门文章

  1. 秀秀偶新购的转角工作台
  2. Spring IOC和MVC基础知识
  3. 【教程】利用libsvm-mat建立分类模型model参数解密【by faruto】
  4. Centos下机器学习算法Mahout库的安装和示例
  5. Ubuntu15.10的64位版本启动eclipse+adt时的若干问题
  6. python3 装饰器_python3装饰器
  7. Get Started with Apex Unit Tests
  8. 超实用!19条Android平台设计规范
  9. [YTU]_2613( 距离产生美)
  10. 人眼中亮斑的检测、定位和去除(2)