@Tyhj
2019-07-19T16:30:25.000000Z
字数 2021
阅读 1853
Android
在Android项目中使用Jni还是比较简单的,新建项目的时候选择Native C++就可以自动配置好Jni项目;但是一个已经存在的项目想要使用Jni就需要自己去写一些配置文件了;其实这些步骤都很简单,而且有助于理解整个Jni的实现过程;
Android studio是通过 CMake 和 NDK 将 C/C++ 代码编译成底层的so库,然后再配合 Gradle 的编译将库打包到 APK 中,所以首先就需要编写CMakeLists.txt文件;
add_library
指定要编译的库,并将所有的 .c 或 .cpp 文件包含指定。include_directories
将头文件添加到搜索路径中set_target_properties
设置库的一些属性target_link_libraries
将库与其他库相关联
在src/main/
路径下新建jni
文件夹,在文件夹下面新建CMakeLists.txt文件
# 设置cmake的最低版本
cmake_minimum_required(VERSION 3.4.1)
# 设置生成的so库的信息
add_library(
#生成的so库的名字
jnitest
# 生成的so库的类型,类型分为两种:
# STATIC:静态库,为目标文件的归档文件
# SHARED:动态库,会被动态链接,在运行时被加载
SHARED
# 设置源文件的位置,可以是很多个源文件,都需要添加进去
jnitest.cpp)
# 从系统里查找依赖库,可添加多个
find_library(
log-lib
# liblog.so库指定的名称为 log,libjnitest.so的名称为jnitest
log)
# 配置目标库的链接,即相互依赖关系
target_link_libraries(
# 目标库(最终生成的库)
jnitest
# 需要依赖的log库,一般情况下,如果依赖的是系统中的库,需要加${}进行引用
# 如果是第三方库,可以直接引用
# 每行引用一个库
${log-lib})
我在里面设置了源文件的路径为jnitest.cpp
,所以在同一目录下新建这个c++文件,文件内容如下:
#include<jni.h>
需要在Gradle中配置cmake文件,点击File/Link C++ Project with Gradle,选择刚才创建的cmake文件,然后会在app的build.gradle文件的Android节点里面添加如下代码;自己去添加也是一样的,目的是配置构建脚本路径
externalNativeBuild {
cmake {
path file('src/main/jni/CMakeLists.txt')
}
}
随便一个Java类中加载jnitest
,调用一下里面的方法,现在里面没有方法,我们可以先在Java中申明,会提示方法不存在,可以自动在C++文件中生成相应方法;
static {
System.loadLibrary("jnitest");
}
public native String helloWorld();
使用C++第一次好像会自动生成一个C文件,没法自动生成方法,自己在C++里面自己写一下就好了
#include<jni.h>
#include <string>
extern "C"
JNIEXPORT jstring JNICALL
Java_com_hikvision_testapp_MainActivity_helloWorld(JNIEnv *env, jobject instance) {
// TODO
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
然后Java中调用这个native方法就是调用了C++的代码了;build一下,就会在如下目录生成so库
![image_1dg4fudg41kjba831apeb8c1khv9.png-28.5kB][1]
也可以在app的build.gradle的Android节点下的defaultConfig节点下面添加如下代码,设置编译的出的so库支持的cup架构
externalNativeBuild{
cmake{
abiFilters "armeabi-v7a","x86"
}
}
可以在其他项目中使用这些so库,只需要在src/main/文件夹下面新建jniLibs文件夹,把生成的so库包括文件夹复制到里面;
使用的时候和刚才的使用是一样的,加载库,创建native方法即可;但是需要注意是是,刚才在C++文件里面是静态注册方法,能通过这个映射方式找到C++中的方法,使用者的包的路径和native方法也必须和之前编译的项目路径一致才可以;感觉先根据so库创建一个library,里面用Java去实现so库的功能,对外提供接口是不错的方法