知识点整理
安卓默认用armeabi-v7a
1.ndk-build
动态加载JNI
1.java 层代码:
static {
System.loadLibrary("MyLibrary"); // libxxx.so库的 libMyLibrary.so
}
2.jni C++
(1)在main目录下新建一个jni目录,里面的.cpp最终要生成.so 库,加载进apk里面
在这里插入代码片
(2) 创建Android.mk Application.mk文件 编译脚本
Android.mk
#每个Android.mk文件必须以LOCAL_PATH开头,在整个开发中,它通常别用做定位资源文件,例如,功能宏my-dir提供给编译系统当前的路径。
LOCAL_PATH := $(call my-dir)
#CLEAR_VARS指编译系统提供一个特殊的GUN MakeFile来为你清除所有的LOCAL_XXX变量,LOCAL_PATH不会被清除。使用这个变量是因为在编译系统时,所有的控制文件都会在一个GUN Make上下文进行执行,而在此上下文中所有的LOCAL_XXX都是全局的。
include $(CLEAR_VARS)
#LOCAL_MODULE变量是为了确定模块名,并且必须要定义。这个名字必须是唯一的同时不能含有空格。会自动的为文件添加适当的前缀或后缀,模块名为“foo”它将会生成一个名为“libfoo.so”文件。
LOCAL_MODULE := myjni
#包含一系列被编译进模块的C 或C++资源文件
LOCAL_SRC_FILES := JNI_C++.cpp
#指明一个GUN Makefile脚本,并且收集从最近“include$(CLEAR_VARS)”下的所有LOCALL_XXX变量的信息,最后告诉编译系统如何正确的进行编译。将会生成一个静态库hello-jni.a文件或者动态库libhello-jni.so。
include $(BUILD_SHARED_LIBRARY)
总结:
LOCAL_PATH即为调用命令的所在目录,你在哪个目录下使用cmd命令,这里就会返回它的路径地址
LOCAL_MODULE你生成的文件名称是什么,输出之后会自动在名称的前后加上lib和.so
LOCAL_SRC_FILES要对哪个文件进行编译
Application.mk
可没有,主要指定so调用库名以及编译的so对应CPU平台
若没有,则可在build.gradle中设置,此时使用系统进行编译,而非使用ndk-build
APP_MODULES := MyJni
APP_ABI := all all代表全平台
3.编译方式选择:
在app module目录下的build.gradle中设置库文件名(生成的so文件名)。找到gradle文件的defaultConfig这项,在里面添加如下内容:
//第一种是将c++ 文件生成.so 库
defaultConfig {
......
//1.指定生成模块名,架构
ndk{
moduleName "JniLibName" //生成的so名字
ldLibs "log", "z", "m" //添加依赖库文件,如果有log打印等
abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定cpu体系结构下的so库。
}
}
//2.指定编译Android.mk目录
externalNativeBuild {
ndkBuild {
path file("src/main/java/jni/Android.mk")
}
}
//3.指定jni代码目录
sourceSets {
main {
jni.srcDirs('src/main/java/jni')
}
}
此种生成的so文件在app/build/intermediates/ndkBuild/debug下
//第二种是 指定将已经有的.so 编译进apk里面
sourceSets {
main {
jniLibs.srcDirs('.\\libs')
这种是指定.so 文件编译进apk里面,如果在main目录下已经有个JniLibs目录则不用指定,编译时自动会编译进去
}
}
2.Cmake方式(常用)
main/java 同级目录 jni jniLibs 这两个目录手动创建后,则在build.gradle中不用指定jni 代码目录和so库路径。
Cmake方式创建步骤:
1.在buidl.gradle里面设置cmake编译模式,设置编译架构,源码so库路径
2.同级目录创建CMakeLists.txt(需要在buidl.gradle里面指定)
3.jni目录里面创建在创建CMakeLists.txt,生成so库
(1)build.gradle
android {
defaultConfig {
....
externalNativeBuild {
cmake {
cppFlags ""
}
}
ndk {
//设置打包时只编译so库armeabi-v7a
moduleName "MyLibrary"
abiFilters 'armeabi-v7a', 'arm64-v8a' ,'x86', 'x86_64'
}
}
externalNativeBuild {
//设置cmake编译脚本
cmake {
path "CMakeLists.txt"
}
}
sourceSets {
//注意如果自己在src/java创建了 jni jniLibs则不用指定,根据需要自己设定
main {
manifest.srcFile 'src/main/AndroidManifest.xml'
java.srcDirs = ['src/main/java', 'src/main/aidl']
resources.srcDirs = ['src/main/java', 'src/main/aidl']
aidl.srcDirs = ['src/main/aidl']
res.srcDirs = ['src/main/res']
assets.srcDirs = ['src/main/assets']
jni.srcDirs = ['src/main/jni', 'src/main/native']
jniLibs.srcDirs 'src/main/jniLibs'
}
}
}
(2) 跟build同级目录创建CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
#添加子目录, 调用子目录中的CMakeLists.txt
set(JNI_PATH ${
CMAKE_CURRENT_SOURCE_DIR}/src/main/jni)
add_subdirectory(${
JNI_PATH})
(3)在src/main jni 里面创建CMakeLists.txt生成so库
cmake_minimum_required(VERSION 3.4.1)
。。。。