1. 环境配置
1.1 安装 ndk,配置环境变量
ndk安装位置:
配置环境变量:
1.2 项目配置 ndk
Android Studio 打开 File / Project Structure / SDK Location / Android NDK location:
1.3 安装CMake
2. 项目配置
2.1 配置 app 的 build.gradle
添加如下节点:
android 节点下 添加配置:
externalNativeBuild { cmake { path "CMakeLists.txt" version "3.10.2" } }
android / defaultConfig 节点下 添加配置:
externalNativeBuild { cmake { cppFlags "" } } ndk { //moduleName"native-xx" //生成的so文件名字,程序中加载so库时需要用到 abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' // 生成so库的CPU平台 }
2.2 /src/目录下创建 CMakeLists.txt
内容如下:
# For more information about using CMake with Android Studio, read the # documentation: https://d.android.com/studio/projects/add-native-code.html # Sets the minimum version of CMake required to build the native library. # 设置构建本地库所需要的CMake最低版本 cmake_minimum_required(VERSION 3.4.1) # 设置生成的so动态库最后输出的路径 src/main/jniLibs set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}) # 创建并命名一个库,设置为静态或共享,并且指定源码的关联路径 # 可以定义多个库,由CMake负责编译它们 # Gradle自动打包并和你的APK包共享这些库 # Creates and names a library, sets it as either STATIC # or SHARED, and provides the relative paths to its source code. # You can define multiple libraries, and CMake builds them for you. # Gradle automatically packages shared libraries with your APK. add_library( # Sets the name of the library. 库名称 native-lib # Sets the library as a shared library. 设置库为共享库 SHARED # Provides a relative path to your source file(s). 源码路径 src/main/cpp/native-lib.c) # 搜索一个明确的预先构建的库并且存储路径变量. # 因为CMake默认在搜索路径中包含了系统库,你仅需明确指定你想添加的公共NDK库的名称即可. # CMake编译库之前会对存在的库进行验证 # Searches for a specified prebuilt library and stores the path as a # variable. Because CMake includes system libraries in the search path by # default, you only need to specify the name of the public NDK library # you want to add. CMake verifies that the library exists before # completing its build. find_library( # Sets the name of the path variable. 设置路径变量的名称 log-lib # Specifies the name of the NDK library that 明确指定你想CMake定位加载的NDK库的名称 # you want CMake to locate. log) # 明确指定CMake应该链接到目标库的库. # 你可以链接多个库,比如自定义脚本/第三方库/系统库 # Specifies libraries CMake should link to your target library. You # can link multiple libraries, such as libraries you define in this # build script, prebuilt third-party libraries, or system libraries. target_link_libraries( # Specifies the target library. 指定目标库 native-lib # Links the target library to the log library 链接目标库到 log 库,包含NDK # included in the NDK. ${log-lib})
2.3 新建 Jni 接口,本地库调用接口
新建 JNI.java类,定义 native 方法:
package com.dongzz.android.javac; /** * C/C++ 代码调用接口 */ public class JNI { //加载本地库 static { System.loadLibrary("native-lib"); } /** * 让C代码做加法运算,把结果返回 * * @param x * @param y * @return */ public native int add(int x, int y); }
2.4 生成 .h 头文件
打开 File / Settings / External Tools / Create Tool,创建工具;
Tool Settings 节点下添加如下配置:
Program : javah Arguments : -classpath . -jni -encoding UTF-8 -d $ModuleFileDir$/src/main/jni $FileClass$ Working directory : $ModuleFileDir$\src\main\java
如图所示:
2.4 JNI类上,右键 / External Tools 执行上步创建的命令
生成 JNI.java 类对应的 .h 头文件:com_dongzz_android_javac_JNI.h
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_dongzz_android_javac_JNI */ #ifndef _Included_com_dongzz_android_javac_JNI #define _Included_com_dongzz_android_javac_JNI #ifdef __cplusplus extern "C" { #endif /* * Class: com_dongzz_android_javac_JNI * Method: add * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_dongzz_android_javac_JNI_add (JNIEnv *, jobject, jint, jint); #ifdef __cplusplus } #endif #endif
2.5 创建C代码包 /src/main/cpp
将 com_dongzz_android_javac_JNI.h
头文件拷贝到 cpp 目录下;
新建 native-lib.c 或 native-lib.cpp 源文件,内容如下:
// // Created by Administrator on 2020/11/5. // #include "com_dongzz_android_javac_JNI.h" #include <string.h> #include <malloc.h> #include <jni.h> /** * 加法运算 * @param env 结构体指针,结构体中包含许多函数 * @param job 实例 谁调用就是谁的实例 * @param a 参数1 * @param b 参数2 * @return */ jint Java_com_dongzz_android_javac_JNI_add (JNIEnv *env, jobject job, jint a, jint b) { int result = a + b; return result; }
执行 Clean Project / Make Project 重新编译项目;/src/main/jniLibs 目录下会生成适应各个CPU平台的 .so 库文件;
3. 常见问题
3.1 More than one file was found with OS independent path lib/armeabi-v7a/libnative_lib.so
解决方案:
app / build.gradle 的 android 节点下添加配置:
// 打包 packagingOptions { //当出现重复文件,会使用第一个匹配的文件打包进入apk //解决 More than one file was found with OS independent path 异常 pickFirst 'lib/armeabi-v7a/libnative-lib.so' pickFirst 'lib/arm64-v8a/libnative-lib.so' pickFirst 'lib/x86_64/libnative-lib.so' pickFirst 'lib/x86/libnative-lib.so' }
重新编译项目,问题解决;