3588开发板大模型apk开发
硬件:Windows11电脑+Linux服务器+3588Android12开发板
软件:vscode+Android studio+adb
目录
方法一:在Android studio中选择3588开发板,进入调试编辑
模型下载

通过modelscope工具下载到服务器上
pip install modelscope #下载工具包
进入目标下载目录,下载模型到当前目录
modelscope download --model testUser/Qwen3-1.7b-Medical-R1-sft model.safetensors --local_dir .

最终下载的文件 也可以直接拉取整个文件夹到目标目录下
模型转换为RKLLM格式(Linux服务器端)
RKLLM-Toolkit 支持将 Hugging Face 格式模型转为 RK3588 适配的.rkllm格式,核心是「加载→校准→量化→编译→打包」。
https://modelscope.cn/models/testUser/Qwen3-1.7b-Medical-R1-sft/file/view/master/model.safetensors?status=2 这个格式模型是SafeTensors格式,是Hugging Face的。
1.准备量化校准数据(dataset.json):
量化需要少量真实数据来校准精度。由于是医疗模型,放入一些医疗相关的问题。 在模型转换目录下创建 dataset.json
[
{"input": "你可以帮我写一份病历吗?", "target": "当然可以,请提供患者的症状。"},
{"input": "感冒了应该吃什么药?", "target": "建议多喝水,可以服用感冒灵。"},
{"input": "什么是高血压?", "target": "高血压是一种常见的心血管疾病。"},
{"input": "肚子疼怎么办?", "target": "请详细描述疼痛的位置和持续时间。"},
{"input": "头痛医头脚痛医脚是什么意思?", "target": "这是一个成语,指只做表面文章。"}
]
2.编写转换脚本 脚本流程 :加载 -> 试跑(校准) -> 压缩(量化) -> 翻译(编译) -> 打包 (参考官方rknn-llm/doc/Rockchip_RKLLM_SDK_CN_1.2.3.pdf at main · airockchip/rknn-llm)
3.运行转换脚本python convert_qwen3_medical_w8a8.py
# 确保RKLLM-Toolkit已安装(参考官方文档)
pip install rknn-llm==1.2.3
# 执行转换
python convert_qwen3_medical_w8a8.py

4.交叉编译demo,验证模型可用性
推送文件到板子上并赋予权限运行


APK开发(Windows PC端)
下载安装Android Studio
1.创建 Native C++ 项目
- 打开 Android Studio,新建项目→选择「Native C++」→下一步;
- 配置项目:
- 名称:qwen3_medical;
- 包名:com.example.qwen3_medical;
- 语言:Java;
- 最小 SDK:Android 12(API 31);
- C++ 标准:C++17;
- 完成创建,自动生成基础工程结构。
2.集成 RKLLM Runtime 资源https://github.com/airockchip/rknn-llm/tree/main
在app/src/main下新建jniLibs/arm64-v8a目录,将 RKLLM SDK 中的librkllmrt.so,libomp.so(路径:rkllm-runtime/Android/arm64-v8a/)复制到该目录。
复制 RKLLM 头文件rkllm.h到app/src/main/cpp目录(与native-lib.cpp 同目录)
项目结构如下图:

3.配置 CMakeLists.txt(这个文件告诉编译器,去哪里找 rkllmrt.so 和 libomp.so 这些工具,然后将它们和 native-lib.cpp 链接到一起)
cmake_minimum_required(VERSION 3.22.1)
project("qwen3_medical")
# 1. 导入预编译的 librkllmrt.so
add_library(rkllmrt SHARED IMPORTED)
set_target_properties(rkllmrt PROPERTIES
# 路径对应你的文件结构:从cpp目录向上到main,再进入jniLibs/arm64-v8a
IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/../jniLibs/arm64-v8a/librkllmrt.so"
)
# 2. 导入预编译的 libomp.so
add_library(libomp SHARED IMPORTED)
set_target_properties(libomp PROPERTIES
IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/../jniLibs/arm64-v8a/libomp.so"
)
# 3. 编译当前项目的C++源码为动态库
add_library(${CMAKE_PROJECT_NAME} SHARED
native-lib.cpp
)
# 4. 链接所有依赖库到目标库
target_link_libraries(${CMAKE_PROJECT_NAME}
# 刚才导入的两个预编译库
rkllmrt
libomp
# 系统基础库
android
log
)
| 配置段 | 作用 |
|---|---|
add_library(rkllmrt SHARED IMPORTED) | 声明导入外部预编译的 librkllmrt.so,而非编译新库 |
IMPORTED_LOCATION | 指定 so 库的实际路径,${CMAKE_SOURCE_DIR}是当前 CMakeLists.txt 所在目录 |
target_link_libraries | 将所有依赖库链接到项目的动态库中,确保运行时能调用到 RKLLM 的函数 |
CMakeLists.txt 修改完成后,需同步配置
- 点击顶部菜单栏的 File → Sync Project with Gradle Files(或点击右上角的「大象 + 刷新」图标);
- 等待同步完成,若控制台无「CMake 配置错误」「找不到 so 文件」等提示,说明基础配置生效;

4..配置build.gradle.kts
确保 Android Studio仅编译 arm64-v8a 架构的 so 库,否则它可能尝试构建 x86 版本,但找不到对应的 .so 库而报错。
打开 app/build.gradle.kts (或 build.gradle),确保有以下配置,强制 APK 只包含 64 位 ARM 代码
android {
// ... 其他配置
defaultConfig {
// ...
externalNativeBuild {
cmake {
cppFlags("")
// 强制指定只编译 64位 ARM 架构
abiFilters("arm64-v8a")
}
}
ndk {
// 打包 APK 时只包含 arm64-v8a 的库
abiFilters += "arm64-v8a"
}
}
}
5.编写 C++ JNI (native-lib.cpp)层代码
JNI 层是 Java 与 C++ 的 “桥梁”,让 Java 层(MainActivity)能调用 C/C++ 写的底层功能(如项目中要调用 RKLLM 模型的加载、推理)。
-
rkllm.h :
这是瑞芯微官方提供的头文件。相当于说明书,规定了可以使用哪些功能、需要传入什么参数、结构体长什么样。它是标准,不能修改。 -
native-lib.cpp 必须严格遵守 rkllm.h 的定义,函数名、参数类型,否则会报错。
6.编写 Java 层逻辑 (MainActivity.java)
注意其中的module path 路径需为开发板上真实的模型路径(需将模型上传到开发板此路径下)
7.编写UI布局(activity_main.xml)
需确保控件的 ID 和 Java 代码里的一致
连接开发板并调试
开发板连接网络,并进入开发者模式,打开开发板的无线调试和网络adb调试。通过adb工具连接到开发板
![]()
方法一:在Android studio中选择3588开发板,进入调试
- 点击 Android Studio 顶部 Run,运行项目 。
-
打开 Logcat:
-
在 Android Studio 底部栏打开 Logcat 标签页。
-
在 Logcat 的搜索框里输入:RKLLM_JNI (这是在 C++ 代码里定义的日志标签)。
-

可以看到模型初始化成功,开发板连接显示器,可在桌面上看到应用,并正常对话交互
方法二:也可以通过adb命令直接安装在板子(推荐方法一)
点击generate apks
在下方可看到build output
项目路径下查看生成的apk文件 通过adb窗口install

之后可以开发板连接显示器,双击桌面的apk运行,并可在PC机cmd命令行中通过logcat命令查看日志。
补充:理解这些文件间的关系
┌─────────────────────────────────────────────────────────────────┐
│ 层级 │ 核心文件 │ 核心职责 │
├──────────────┼─────────────────────────────────────────────┼─────────────────────────────────┤
│ UI层 │ activity_main.xml │ 定义界面布局(控件、样式) │
├──────────────┼─────────────────────────────────────────────┼─────────────────────────────────┤
│ Java业务层 │ MainActivity.java │ 处理UI交互、调用JNI、管理对话逻辑 │
├──────────────┼─────────────────────────────────────────────┼─────────────────────────────────┤
│ JNI桥接层 │ native-lib.cpp + rkllm.h │ 连接Java与C++,调用RKLLM接口 │
├──────────────┼─────────────────────────────────────────────┼─────────────────────────────────┤
│ RKLLM运行时 │ librkllmrt.so + libomp.so │ 提供NPU加速推理的底层实现 │
├──────────────┼─────────────────────────────────────────────┼─────────────────────────────────┤
│ 模型文件 │ qwen3_medical_rk3588_w8a8.rklm │ 医疗模型的权重与编译指令(NPU可执行)│
├──────────────┼─────────────────────────────────────────────┼─────────────────────────────────┤
│ 编译配置层 │ CMakeLists.txt + app/build.gradle │ 控制代码编译、依赖链接、APK打包 │
└─────────────────────────────────────────────────────────────────┘
1.Java 层负责 UI 交互,调用 JNI 接口,实现多轮对话逻辑
-
调用 C++ 的 initModel 和 chat 接口。
-
接收 C++ 回调回来的文字,显示在屏幕上。
-
负责拼接历史对话(Prompt Engineering),保证多轮对话连贯。
RKLLM 的 chat 接口是无状态的。要实现多轮对话,需要在 Java 里把历史对话拼接到一起
-
多轮对话状态维护:
-
在 Java 层维护一个 StringBuilder promptBuilder。
-
用户发消息 -> promptBuilder.append(用户格式)。
-
调用推理 -> 模型生成文本 -> 存入 currentAiResponse。
-
推理结束 -> promptBuilder.append(currentAiResponse + IM_END)。
-
下一轮 -> 再次发送整个 promptBuilder.toString()。
-
2.native-lib.cpp 的核心作用
- 让 Java 能调用 C++ 函数(正向调用);
- 让 C++ 能回调 Java 方法(反向调用);
- 完成跨语言的数据类型转换;
- 封装底层 C++ 库的调用逻辑(屏蔽 RKLLM 的复杂接口)。
我们可以把开发这个 App 比作 “开一家餐厅”:
-
build.gradle.kts (总管/施工队队长)
-
作用:它负责指挥整个编译过程。它告诉编译器:“我们要造一个 Android App,请把 Java 代码编译好,然后去调用 CMake 把 C++ 代码也编译好,最后打包成一个 APK 安装包。”
-
.so 库只有 arm64-v8a (RK3588 专用) 的版本。如果不告诉总管“只做 arm64 的菜”,总管默认会尝试做 x86(电脑模拟器)或 32位 ARM 的菜,结果发现没有配料,就会报错。
-
-
CMakeLists.txt (后厨装修图纸)
-
作用:它告诉 C++ 编译器:“去哪里找 rkllmrt.so 和 libomp.so 这些工具,然后把它们和 native-lib.cpp 焊接到一起。”
-
-
native-lib.cpp (后厨大厨/翻译官)
-
作用:这是连接 Java (前台) 和 .so 库 (核心引擎) 的桥梁。
-
Android Studio 生成的默认代码只会说一句 “Hello from C++”。需要把它删掉,重写成调用 RKLLM 模型初始化、推理、对话的代码。如果不改,App 虽然能运行,但没有任何 AI 功能。
-
-
MainActivity.java (前台服务员/菜单)
-
作用:负责把用户的输入(菜单)传给后厨,并把后厨做好的结果(AI 回复)端给用户看。
-
需要在这里写逻辑去调用 native-lib.cpp 里的函数。
-
更多推荐


所有评论(0)