Android JNI开发01—调用非JNI标准的动态链接库
JNI标准库文件
在Android中的JNI机制主要用于Java对C/C++调用,为了让这种调用最为简单,Google设计了一套完整的游戏规则,当所有的接口文件都按照这套规则去设计的时候,开发着在调用的时候才会最简单。这套标准简单来说包括一个Java层的接口文件,一个JNI实现的头文件和一个根据JNI标准编写的cpp文件编译出的动态链接库组成,如下:
- Java接口文件
public class JNIUtils {
public static native int addFromJNI(int a, int b);
}
- JNI实现头文件
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include "JniTest.h"
/* Header for class com_wujian_jnidemo_JNIUtils */
#ifndef _Included_com_wujian_jnidemo_JNIUtils
#define _Included_com_wujian_jnidemo_JNIUtils
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_wujian_jnidemo_JNIUtils
* Method: addFromJNI
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_wujian_jnidemo_JNIUtils_addFromJNI
(JNIEnv *, jclass, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
对应的还会有一个cpp文件实现这个头文件中的函数
#include "com_wujian_jnidemo_JNIUtils.h"
/*
* Class: com_wujian_jnidemo_JNIUtils
* Method: addFromJNI
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_wujian_jnidemo_JNIUtils_addFromJNI
(JNIEnv *, jclass, jint a, jint b)
{
return a+b;
}
这个cpp最终根据平台编译出对应的动态链接库这个库的名字是自己在cmakelist中定义的
非JNI标准库文件
相对应的还有不按照JNI标准编译的库文件,这些动态链接库往往是各个平台共用的,不一定只是在Android中被使用,so文件所对应的cpp文件和头文件完全是按照标准的cpp或者c语言格式编写的,比如写一个很简单的加法的函数并吧这个函数编译成动态链接库,代码如下:
//JniTest.h
#include<stdio.h>
int funcAdd(int a, int b);
//JniTest.c
#include"JniTest.h"
int funcAdd(int a, int b)
{
return a+b;
}
创建一个名叫jnitest的文件夹中,然后在jnitest下创建一个名叫jni的子目录,将这两个文件拷贝到jni下面,然后在这个目录中创建两个文件,分别为Android.mk和Application.mk
#Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := jnitest
LOCAL_SRC_FILES := JniTest.c
# 添加对log库的支持
LOCAL_LDLIBS:=-L$(SYSROOT)/usr/lib -llog
# 注:若生成static的.a,只需添加 LOCAL_LDLIBS:=-llog
include $(BUILD_SHARED_LIBRARY)
LOCAL_PATH := $(call my-dir)
#Application.mk
APP_ABI := all
APP_BUILD_SCRIPT := Android.mk
此时jni目录下应该有这些文件
在jni目录下启动terminal或者命令行,使用ndk-build编译(ndk命令的配置省略),编译完成如下图,并且会在jni的同级目录下创建一个libs的目录,里面就是各个平台对应的动态链接库,文件名叫libjnitest.so
libjnitest.so是一个典型的非JNI标准的动态链接库,他没有对应的Java接口,没有对应的JNI头文件,现在很多第三方的SDK都是提供这种库文件,同时还会提供一个对应的头文件相当于上述的JniTest.h,为了能在JNI开发中正常调用这种ku文件中的方法,一般需要在他的外面再封装一层JNI,通过JNI去调用这个库中的方法,然后自己向java层提供调用的接口