上一篇我们用"钞能力"(Chaquopy + Paddle)快速搞定了功能,但代价是惨痛的------APK 体积可能飙升到了 100MB+。这在用户眼里就是"毒瘤软件"。
今天,我们不仅要当"大厨",还要当"外科医生"。我们将对这个 APK 进行一场精准的瘦身手术 ,目标是将体积压缩到 30MB 以内,同时保留 Python 的开发体验。
1. 诊断报告:为什么它这么"胖"?
在动刀之前,我们先得知道脂肪堆积在哪里。一个典型的 Chaquopy + Paddle APK 结构如下:
-
Android 基础代码:< 5MB(忽略不计)
-
Python 解释器 + 标准库:~10MB(这是基础开销)
-
Native 库 (.so 文件) :~80MB+ (罪魁祸首) 🚨
- PaddlePaddle 包含了完整的训练框架、反向传播逻辑、多种硬件驱动......但你在手机上只需要推理(Inference)。
手术方案:
-
切除多余肢体:只保留一种 CPU 架构。
-
更换核心引擎 :用轻量级的 ONNX Runtime 替换笨重的 PaddlePaddle 库,但依然使用 Paddle 训练的模型。
2. 第一刀:ABI 架构过滤 (减重 50%)
Android 手机 CPU 有多种架构(x86, armeabi-v7a, arm64-v8a)。默认情况下,Gradle 会把所有架构的 .so 库都打包进去,就像你出门旅行带了春夏秋冬四季的衣服。
但在 2024 年,99% 的主流手机都是 arm64-v8a。
🛠 操作指南
修改 app/build.gradle:
Groovy
android {
defaultConfig {
// ...
ndk {
// ✂️ 咔嚓!只保留 64位 ARM 架构
// 这会直接丢弃 x86 和 32位 ARM 的库文件
abiFilters "arm64-v8a"
}
}
}
效果 :如果你的 APK 里原本包含三套 .so 文件,这一步直接能让体积减少 2/3。
3. 第二刀:引擎置换手术 (减重核心)
这是最关键的一步。pip install paddlepaddle 安装的是一个通用型巨无霸。
核心思路:
-
训练时:在电脑上用 PaddlePaddle(功能全,体积大)。
-
部署时 :在手机上用 ONNX Runtime(专注推理,体积极小)。
ONNX (Open Neural Network Exchange) 是 AI 界的"通用货币"。所有的模型(PyTorch, TensorFlow, Paddle)都可以转换成 ONNX 格式,然后用同一个轻量级引擎运行。
步骤 A:模型转换 (在电脑上操作)
首先,把你的 Paddle 模型转换成 .onnx 文件。百度贴心地提供了 paddle2onnx 工具。
Bash
# 1. 安装转换工具
pip install paddle2onnx
# 2. 转换模型 (假设你的模型存放在 inference_model 文件夹)
paddle2onnx --model_dir ./inference_model \
--model_filename model.pdmodel \
--params_filename model.pdiparams \
--save_file mobile_model.onnx \
--opset_version 11
现在你得到了一个通用的 mobile_model.onnx。
步骤 B:修改 Gradle 依赖 (Android端)
修改 app/build.gradle 的 Python 配置,把巨大的 paddle 换成小巧的 onnxruntime。
Groovy
defaultConfig {
python {
pip {
// ❌ 移除这个巨无霸
// install "paddlepaddle==2.5.0"
// ✅ 换成这个轻量级选手 (约 5-8MB)
install "onnxruntime"
install "numpy" } } }
步骤 C:重写 Python 推理代码
我们需要修改 ai_engine.py,把 Paddle 的调用换成 ONNX Runtime 的调用。逻辑几乎一样,只是 API 变了。
Python
# src/main/python/ai_engine.py
import numpy as np
import onnxruntime as ort
from os.path import dirname, join
class AIModel:
def __init__(self):
# 获取模型路径 (假设你把 onnx 文件放在了 src/main/python 目录下)
model_path = join(dirname(__file__), "mobile_model.onnx")
# 初始化 ONNX 推理会话
#这是最耗时的步骤,建议在后台线程做
self.session = ort.InferenceSession(model_path)
# 获取输入层名称 (就像知道插座的形状)
self.input_name = self.session.get_inputs()[0].name
def predict(self, input_data):
# 1. 数据预处理 (和之前一样,转为 numpy)
# 注意:ONNX 对数据类型要求很严,必须匹配模型定义 (通常是 float32)
data = np.array([[float(input_data)]], dtype=np.float32)
# 2. 执行推理
# run(输出节点名列表, 输入字典)
result = self.session.run(None, {self.input_name: data})
# 3. 解析结果
# result 是一个列表,取出第一个输出
raw_val = result[0][0][0]
return f"ONNX 极速推理结果: {raw_val:.2f}"
4. 进阶深潜:压榨最后 1MB
如果你对体积有极致的强迫症,这里还有两个"黑魔法":
技巧 1:移除 Python 标准库中的废物
Chaquopy 默认会打包完整的 Python 标准库(包括你根本用不到的 email, html, multiprocessing 等模块)。
在 build.gradle 中可以配置剔除:
Groovy
python {
// ...
pyc {
// 编译成 pyc 字节码,加载更快,体积更小
src false
}
// 剔除不需要的标准库模块
extractPackages "json", "os", "sys" // 仅举例,慎用
}
注意:通过 buildPython 自定义 Python 构建来剔除标准库比较复杂,通常对于新手,开启 .pyc 编译已经能节省不少空间。
技巧 2:动态加载模型
不要把 .onnx 模型文件打包在 APK 的 assets 或 python 目录里。
-
做法:APK 里只放代码。用户第一次打开 App 时,从你的服务器下载模型文件到手机本地目录。
-
收益:APK 体积瞬间减少 5MB - 50MB(取决于模型大小)。
📊 瘦身成果对比
| 优化阶段 | 包含组件 | 预估 APK 大小 | 备注 |
|---|---|---|---|
| 原始版 | PaddlePaddle + 全架构 .so | 120MB+ | 用户看到会被吓跑 |
| 阶段一 | abiFilters "arm64-v8a" | 60MB | 砍掉了一半,但还是大 |
| 阶段二 | ONNX Runtime 替换 Paddle | 25MB | 达成目标! 🎯 |
| 阶段三 | 开启 pyc 编译 + 移除冗余库 | 18MB | 极致轻量 |
🏁 总结
要让 Python AI 应用在 Android 上兼顾开发效率和落地体验,核心逻辑是:
"Python 写逻辑,ONNX 做引擎,Gradle 砍架构。"
-
ABI Filter 是必须的。
-
Paddle/PyTorch/TF 只是训练工具,不要把它们带进 APK。
-
ONNX Runtime 是端侧部署的最佳伴侣。
🚀 Next Step
现在你的 App 既聪明又轻盈。但还有一个问题:安全性。
你的 Python 代码和模型文件在 APK 里几乎是"裸奔"的,黑客解压 APK 就能拿到你的核心算法。