1、源文件
将以下简单的一个C程序打包成动态SO库提供给安卓使用。
- 头文件
//
// Created by DELL on 2022/9/1.
//
#include
#ifndef UNTITLED_DEMO_H
#define UNTITLED_DEMO_H
#endif //UNTITLED_DEMO_H
int testDemo();
- 实现文件
//
// Created by DELL on 2022/9/1.
//
#include "demo.h"
int testDemo() {
printf("Hello, Get World!\n");
return 889;
}
int main(){
testDemo();
}
#include
int testStatic() {
printf("Hello, Get World!\n");
return 3333;
}
#include
int get() {
printf("Hello, Get World!\n");
return 199;
}
2、Linux平台打SO动态库
(1)Linux平台下载安装NDK
wget https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip? hl=zh_cn
(2)重命名解压
修改成.zip mv android-ndk-r17c-linux-x86_64.zip?hl=zh_cn android-ndk-r17c-linux- x86_64.zip
解压unzip android-ndk-r17c-linux-x86_64.zip
(3)配置全局环境变量
vim /etc/profile
#配置NDK路径
export NDK="/root/NDK/tool/android-ndk-r17c"
#配置GCC
export NDK_GCC_x86="/root/NDK/tool/android-ndk-r17c/toolchains/x86-4.9/prebuilt/linux-x86_64/bin/i686-linux-android-gcc"
export NDK_GCC_x64="/root/NDK/tool/android-ndk-r17c/toolchains/x86_64-4.9/prebuilt/linux-x86_64/bin/x86_64-linux-android-gcc"
export NDK_GCC_arm="/root/NDK/tool/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc"
export NDK_GCC_arm64="/root/NDK/tool/android-ndk-r17c/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-gcc"
#配置寻找库文件、头文件、asm
#arch-arm arch-arm64 arch-mips64 arch-x86 arch-x86_64
export NDK_CFIG_x86="--sysroot=/root/NDK/tool/android-ndk-r17c/platforms/android-21/arch-x86 -isystem /root/NDK/tool/android-ndk-r17c/sysroot/usr/include -isystem /root/NDK/tool/android-ndk-r17c/sysroot/usr/include/i686-linux-android"
export NDK_CFIG_x64="--sysroot=/root/NDK/tool/android-ndk-r17c/platforms/android-21/arch-x86_64 -isystem /root/NDK/tool/android-ndk-r17c/sysroot/usr/include -isystem /root/NDK/tool/android-ndk-r17c/sysroot/usr/include/x86_64-linux-android"
export NDK_CFIG_arm="--sysroot=/root/NDK/tool/android-ndk-r17c/platforms/android-21/arch-arm -isystem /root/NDK/tool/android-ndk-r17c/sysroot/usr/include -isystem /root/NDK/tool/android-ndk-r17c/sysroot/usr/include/arm-linux-androideabi"
export NDK_CFIG_arm64="--sysroot=/root/NDK/tool/android-ndk-r17c/platforms/android-21/arch-arm64 -isystem /root/NDK/tool/android-ndk-r17c/sysroot/usr/include -isystem /root/NDK/tool/android-ndk-r17c/sysroot/usr/include/aarch64-linux-android"
#配置AR 用于打包静态库
export NDK_AR_x86="/root/NDK/tool/android-ndk-r17c/toolchains/x86-4.9/prebuilt/linux-x86_64/bin/i686-linux-android-ar"
export NDK_AR_x64="/root/NDK/tool/android-ndk-r17c/toolchains/x86_64-4.9/prebuilt/linux-x86_64/bin/x86_64-linux-android-ar"
export NDK_AR_arm="/root/NDK/tool/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-ar"
export NDK_AR_arm64="/root/NDK/tool/android-ndk-r17c/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-ar"
(4)打动态so库
以上配置了四个平台、x86、x86_64、arm,arm64。使用相应的环境变量打包生成相应平台的so库。例如打x86平台的so执行如下:
$NDK_GCC_x86 $NDK_CFIG_x86 -fPIC -shared demo.c -o libdemo.so
因此四个平台打包的命令分别如下:
$NDK_GCC_x86 $NDK_CFIG_x86 -fPIC -shared demo.c -o libdemo.so
$NDK_GCC_x64 $NDK_CFIG_x64 -fPIC -shared test.c -o libtest.so
$NDK_GCC_arm $NDK_CFIG_arm -fPIC -shared test.c -o libtest.so
$NDK_GCC_arm64 $NDK_CFIG_arm64 -fPIC -shared test.c -o libtest.so
这样我们就生成了对于平台的so库。
(4)打静态a库
#打包静态库
$NDK_GCC_x86 $NDK_CFIG_x86 -fPIC -c static.c -o libstatic.o
$NDK_AR_x86 rcs -o libstatic.a libstatic.o
3、动态so库、静态a库集成到Android环境
(1)将so库集成到jnilibs中
(2)将静态a库集成as中
(3)配置Cmake
#cmake_minimum_required(VERSION 3.4.1) # 最低支持Cmake版本
cmake_minimum_required(VERSION 3.10.2)# 最低支持Cmake版本
# Declares and names the project.
project("jni_02")
#NDK集成C库流程
#1、导入C库头文件 inc
include_directories("inc")
#2、配置总库,也就是最终打包到APK里的库
file(GLOB allCPP *.c *.h *.cpp)
add_library(
native-lib # Sets the name of the library 给最终打包到APK的C库起名称 native-lib
SHARED # Sets the library as a shared library.//设置库为动态共享库
${allCPP} # Provides a relative path to your source file(s).//导入所有源文件
)
#导入静态库【第二方式】 可读性更强,代码多
add_library(static STATIC IMPORTED)
set_target_properties(static PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libstatic.a)
# 导入动态库 【第二方式】 可读性更强,代码多
#add_library(getndk SHARED IMPORTED)
#set_target_properties(getndk PROPERTIES
#IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}/libgetndk.so)
#导入动态库 【第一种方式】简单,不易理解 ,CMAKE_ANDROID_ARCH_ABI会自动匹配当前的CPU架构,
##设置so文件夹
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}")
#这种方式是一个个添加
#add_library( # Sets the name of the library.
# jni_01
# # Sets the library as a shared library.
# SHARED
# # Provides a relative path to your source file(s).
# native-lib.cpp extern-lib.cpp)
#4、链接具体的库,到我们的 libnative-lib.so总库
target_link_libraries(
native-lib
#${log-varAAAA}
log # 自动寻找 # 具体的库 链接到 libnative-lib.so里面去
fmod # 具体的库 链接到 libnative-lib.so里面去
fmodL # 具体的库 链接到 libnative-lib.so里面去
test # 具体的库 链接到 libnative-lib.so里面去
demo # 具体的库 链接到 libnative-lib.so里面去
static # 具体的库 链接到 libnative-lib.so里面去
)
(3)配置Gadle
(4)测试
- 初始化加载lib
static {
System.loadLibrary("native-lib");
System.loadLibrary("test");
System.loadLibrary("demo");
}
- JNI测试
binding.btnMySo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
testMySo();
}
});
native void testMySo();
// 我先声明 int get(),运行后,你自己去找 实现(libtest.so 库里面的实现),如果找不到报错
extern "C" { // 由于库 是C编写的,必须采用C的编译方式
extern int get();
}
extern "C" { // 由于库 是C编写的,必须采用C的编译方式
extern int testDemo();
}
extern "C" { // 由于库 是C编写的,必须采用C的编译方式
extern int testStatic();
}
extern "C"
JNIEXPORT void JNICALL
Java_com_it_jni_102_MainActivity_testMySo(JNIEnv *env, jobject thiz) {
LOGD("test my so")
jint result = testDemo();
jint result2 = get();
jint result3 = testStatic();
LOGD("testDemo value is %d",result);
LOGD("get value is %d",result2);
LOGD("testStatic value is %d",result3);
}
2022-09-01 14:34:09.596 4375-4375/com.it.jni_02 D/Native: test my so
2022-09-01 14:34:09.596 4375-4375/com.it.jni_02 D/Native: testDemo value is 889
2022-09-01 14:34:09.596 4375-4375/com.it.jni_02 D/Native: get value is 199
2022-09-01 14:34:09.596 4375-4375/com.it.jni_02 D/Native: testStatic value is 3333