安卓逆向在Android Studio中编写SO文件并测试调用 (四)
一、准备工作
Android Studio 版本: 2024.3
JDK 版本: 17
新建项目前,请先确认 NDK 已安装:File → Settings → Android SDK → SDK Tools,勾选 NDK (Side by side) 和 CMake ,点击 Apply 安装。

二、创建 Native C++ 项目
- 打开 Android Studio,点击 New Project ,选择 Native C++ 模板(注意不是 Empty Activity)。
- 填写项目信息:
- Name :
HelloJNI - Package name :
com.example.hellojni - Minimum SDK:API 21(NDK 建议的最低版本)
- Language:Java 或 Kotlin 均可
- Name :
- 点击 Finish,等待项目构建完成。
项目会自动生成以下核心文件:
MainActivity:Java/Kotlin 层,包含native方法声明和System.loadLibrary()调用。native-lib.cpp:C++ 层,实现native方法的具体逻辑。CMakeLists.txt:CMake 构建脚本,配置 SO 库的编译规则。
三、编写 JNI 方法
3.1 在 Java/Kotlin 层声明 native 方法(可选)
打开 MainActivity,默认已经有一个 stringFromJNI() 方法:
java
public native String stringFromJNI();
如果需要添加新方法,只需在类中声明:
java
public native int add(int a, int b);
3.2 在 C++ 层实现 native 方法
打开 native-lib.cpp,按以下 JNI 函数命名规则实现:
cpp
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_hellojni_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
函数名规则 :
Java_包名_类名_方法名,包名中的.替换为_。
3.3 配置 CMakeLists.txt
项目自动生成的 CMakeLists.txt 通常位于 app/src/main/cpp/ 目录下,内容如下:
cmake
cmake_minimum_required(VERSION 3.22.1)
project("hellojni")
add_library(
hellojni
SHARED
native-lib.cpp
)
find_library(log-lib log)
target_link_libraries(
hellojni
${log-lib}
)
默认配置已满足需求,一般无需修改。
3.4 在 build.gradle.kts 中配置 NDK 和 CMake
项目会自动生成 externalNativeBuild 配置,确认 app/build.gradle.kts(或 build.gradle)中包含:
kotlin
android {
...
defaultConfig {
...
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
externalNativeBuild {
cmake {
path = file("src/main/cpp/CMakeLists.txt")
version = "3.22.1"
}
}
}
如需指定 CPU 架构(减少包体积),可在 defaultConfig 中添加:
kotlin
ndk {
abiFilters.addAll(listOf("armeabi-v7a", "arm64-v8a"))
}
若不配置,SO 文件将默认生成到所有支持的架构目录中。
四、编译生成 SO 文件
-
点击菜单栏 Build,选择编译(或按
Ctrl+F9)。 -
编译完成后,生成的 SO 文件位于:
app/build/intermediates/xx/各架构目录下均可找到
libhellojni.so文件。 -
如需获取 Release 版,可将 Build Variant 切换为 release 后再执行编译。


五、调用并测试 SO 方法
由于 AS 2024.3 的默认布局中 MainActivity 已包含加载 SO 库和调用 stringFromJNI() 的示例代码,直接运行 App 即可验证。
5.1 确保 MainActivity 中已加载 SO 库
java
static {
System.loadLibrary("hellojni");
}
5.2 在界面中调用 native 方法
找到 onCreate 方法,已有示例:
java
TextView tv = findViewById(R.id.sample_text);
tv.setText(stringFromJNI());
5.3 运行 App
连接设备或启动模拟器,点击 Run 。界面应显示 Hello from C++,表示 SO 库加载成功,native 方法被正确调用。
5.4 查看 Logcat 确认 SO 加载信息
打开 Logcat 窗口,筛选 hellojni 或 native,可看到类似以下信息:
2026-06-01 10:00:00.000 12345-12345/? I/hellojni: Loading native library...
说明 SO 库已成功加载并运行。
六、SO 库导出和引用
如需将生成的 SO 库提供给其他项目使用:
-
复制 SO 文件 :从
app/build/intermediates/xx/中提取各架构目录下的libhellojni.so。 -
在目标项目中配置:
-
在目标 App 的
src/main/目录下创建jniLibs文件夹。 -
按架构将 SO 文件放入对应子目录,如
jniLibs/arm64-v8a/libhellojni.so。 -
在
build.gradle中添加sourceSets配置:kotlinandroid { sourceSets { main { jniLibs.srcDirs = ['src/main/jniLibs'] } } }
-
-
使用 SO 库 :将原 Java/Kotlin 类(包含
native方法声明的类)完整复制到新项目中,注意 包名和类名必须与原项目完全相同 ,否则会报UnsatisfiedLinkError。
七、如何生成 .h 头文件
在 Android Studio 的 Native C++ 项目中,.h 头文件 不会自动生成,需要根据你的接口定义方式手动创建或通过工具生成。下面分两种常见场景说明。
7.1 纯 C/C++ 库(无 JNI,供其他 C/C++ 代码调用)
手动编写头文件 。
在 app/src/main/cpp 目录下新建 mylib.h,内容示例:
cpp
// mylib.h
#ifndef MYLIB_H
#define MYLIB_H
#ifdef __cplusplus
extern "C" {
#endif
int add(int a, int b);
#ifdef __cplusplus
}
#endif
#endif
然后在 mylib.cpp 中实现,并在 CMakeLists.txt 中正常添加。
生成的头文件直接用于其他 C/C++ 项目的 #include。
7.2 JNI 库(供 Java/Kotlin 调用)
头文件需要根据 Java 中的 native 方法声明自动生成,保证函数签名与 JNI 规范一致。
7.2.1 编写 Java 类(声明 native 方法)
例如在 com.example.hellojni 包下创建 MyJNI.java:
java
package com.example.hellojni;
public class MyJNI {
static {
System.loadLibrary("hellojni");
}
public static native String stringFromJNI();
public static native int add(int a, int b);
}
7.2.2 编译 Java 类生成 .class 文件
在 Android Studio 中点击 Build → Assemble Project(或按 Ctrl+F9)。
.class 文件会生成在 \app\build\intermediates\javac\release\compileReleaseJavaWithJavac\classes\com\example\hellojni\MyJNI.class。
7.2.3 使用 javac -h 生成 JNI 头文件
打开 Android Studio 的 Terminal,执行:
bash
cd app/src/main/java
javac -h ../../cpp com/example/hellojni/MyJNI.java
-h ../../cpp:指定头文件输出到app/src/main/cpp目录。- 后面的路径是 Java 源文件相对于当前目录的位置。
执行后,会在 app/src/main/cpp 下生成 com_example_hellojni_MyJNI.h,内容包含:
cpp
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_hellojni_MyJNI */
#ifndef _Included_com_example_hellojni_MyJNI
#define _Included_com_example_hellojni_MyJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_hellojni_MyJNI
* Method: stringFromJNI
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_hellojni_MyJNI_stringFromJNI
(JNIEnv *, jclass);
/*
* Class: com_example_hellojni_MyJNI
* Method: add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_example_hellojni_MyJNI_add
(JNIEnv *, jclass, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
7.2.4 在 C++ 代码中实现头文件声明的函数
在 native-lib.cpp 中:
cpp
#include "com_example_hellojni_MyJNI.h"
JNIEXPORT jstring JNICALL Java_com_example_hellojni_MyJNI_stringFromJNI(JNIEnv *env, jclass clazz) {
return env->NewStringUTF("Hello from JNI");
}
JNIEXPORT jint JNICALL Java_com_example_hellojni_MyJNI_add(JNIEnv *env, jclass clazz, jint a, jint b) {
return a + b;
}
7.2.5 编译生成 .so 文件
按之前的操作 Ctrl+F9,.so 文件会出现在 app/build/intermediates/xx/... 等路径中。
八.其他项目如何使用你的 .h + .so
C++ 调用 和 Java 调用 两种场景。
8.1 Java 调用
纯 Java/Kotlin 代码,通过 JNI 调用 native 方法。
只需要 .so 文件和 Java 包装类,不需要 .h 头文件,也不需要 CMake。
8.1.1 交付物
交付物/
├── jniLibs/
│ ├── arm64-v8a/
│ │ └── libhellojni.so
│ ├── armeabi-v7a/
│ │ └── libhellojni.so
│ ├── x86/
│ │ └── libhellojni.so
│ └── x86_64/
│ └── libhellojni.so
└── MyJNI.java (Java 包装类)
8.1.2 使用方操作步骤
-
放置 SO 文件
在
app/src/main/jniLibs/下按架构创建子目录(如arm64-v8a),将对应的.so文件放进去。 -
复制 Java 包装类
将
MyJNI.java复制到项目的java目录下,保持原包名不变 (例如com.example.hellojni)。 -
在代码中直接调用
javaimport com.example.hellojni.MyJNI; int result = MyJNI.add(1, 2); -
可选:限制打包架构 (减少 APK 体积)
在
app/build.gradle中添加:kotlindefaultConfig { ndk { abiFilters.addAll(listOf("arm64-v8a", "armeabi-v7a")) } }
不需要 :.h 头文件、CMakeLists.txt、cpp 目录、externalNativeBuild 配置。

8.2 C++ 调用(其他 Native 库调用的 SO)
使用方有自己的 C++ 代码,需要直接调用你库中的函数(非 JNI 入口)。
需要同时提供 .h 头文件和 .so 库,并配置 CMake。
8.2.1 交付物
交付物/
├── include/
│ └── com_example_hellojni_MyJNI.h (或纯 C++ 头文件)
└── lib/
├── arm64-v8a/
│ └── libhellojni.so
└── armeabi-v7a/
└── libhellojni.so
8.2.2 使用方操作步骤
-
放置文件
- 将
.h文件放入app/src/main/cpp/include/ - 将
.so文件按架构放入app/src/main/cpp/lib/${ANDROID_ABI}/
- 将
-
配置 CMakeLists.txt
-
在 C++ 代码中
#include并调用
总结
-
纯 C/C++ 库 :
.h手动编写。 -
JNI 库 :使用
javac -h根据 Java native 方法生成.h。