android ndk本质就是java的jni 就是用java调用c代码,在windows上jni是通过java调用的dll动态链接库,在android平台上使用的库是.so库。
也就是说我们需要将c代码编译成.os的库提供给java调用。
首先我们需要了解一下android平台的cpu类型(不同的cup它的指令集不同需要不同的库)。
android平台常见的cpu类型有
armeabi armeabi-v7a
"armeabi"代表的是ARM嵌入式应用程序二进制接口 v7a 是指的不同的架构,ARM架构最初版本是v1,每种架构都有一系列处理器在使用。
比如 ARM7/ARM9/ARM10使用的是v5架构,Cortex系列使用的是v7架构。也就是说不同的架构需要不同的c库文件。
x86(intel架构)
mips
java调用c代码的步骤就是
编写java端调用c端的java代码
编写c端的代码
用ndk编译c端的代码
java调用c代码
java端代码
package com.suse.yuxin.ndkdemo;
/**
* 测试ndk
* Created by yuxin on 2016/8/27.
*/
public class Fibonacci {
public static native long recursiveNative(int i);
}
java端的代码只需要声明一个native的方法,告诉编译器这个是一个调用c的方法。至于这个方法是public private 或者是protect那就随便你了。声明为静态仅仅只是方便调用。
编写c端的代码
需要一个和java端的native方法对应起来的头文件(可以使用javah命令来生成)。
javah 后面的参数 -classpath是你声明java代码的路径 需要注意的是后面的文件名是包含了包名的,所以这个路径是去除了包名之后的路径 -d是指的声明的头文件的目录
这个就是用javah生成的头文件 可以看到只有一个函数声明
接下来需要做的就是实现这个c函数
这里只是做了简单的实现 返回了一个0
用ndk编译c代码将c编译成.os库
ndk我这里用的是ndk-r10d 没有的同学可以自行下载
在编译我们的c代码之前我们需要告诉ndk要怎么编译,有哪些文件需要编译,需要编译那些cpu对应的库,为此我们需要添加两个配置文件。(这两个配置文件都可以在ndk提供的例子里面找到 我这里是直接复制的hello-jni里面的
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := fibonacci
LOCAL_SRC_FILES := Fibonacci.c
include $(BUILD_SHARED_LIBRARY)
Local_path 指的是本地的路径也就是andorid.mk的路径
第二行是清除掉除了LOCAL_PATH 之外的所有LOCAL_XXX变量,免得错误定义
第三行是定义编译出来的os库的文件名
第四行是需要编译的c文件
Application.mk
APP_ABI := all
指定需要编译的cpu平台 这里是全部平台都需要,最后编译出来的平台是看你的ndk版本支持那些平台,一般来说版本比较新的nsk支持的平台更多。
接下来我们就可以开始编译os库了 编译使用的是ndk 自带的命令 ndk-build (最好是配置哈ndk环境变量)
到此库已经生成。
在java端使用os库(android ide使用的是andorid studio)
使用库的时候需要先加载库,加载使用的是static代码块加载。这样的话在虚拟机加载类的时候就会加载库,调用的时候肯定就是加载完成了的。
最后看看调用效果吧