当前位置: 首页 > news >正文

【NDK / JNI】Sceneform-EQR 集成 Filament JNI 源码:关键点与逐步操作记录 - EQ

摘要:
在 Sceneform-EQR 项目中,原有对 Filament 的使用方式仅依赖官方预编译产物,Native 层不可控且 SO 体积较大。
为提升工程可维护性并优化产物体积,本文记录了在不修改 Filament Java API 的前提下,引入 Filament JNI 源码、合并 filament-android / filament-utils-android / gltfio-android 三个模块,并统一 JNI_OnLoad 的完整实践过程。

Sceneform-EQR 集成 Filament JNI 源码的工程优化实践

结论:从 Java-only 依赖到 Native 一体化编译,压缩 SO 体积 35%+
so库从4.3M压缩至2.8M

仓库地址:https://github.com/eqgis/Sceneform-EQR/tree/dev-withFilamentCpp

一、项目优化背景

1. Sceneform-EQR 与 Filament 的现状

Sceneform-EQR 本质上是一个基于 Filament 的 Android 3D / AR 渲染框架
在现有工程结构中:

  • Java 层:直接依赖 Filament 官方提供的 Java API

  • Native 层:使用官方预编译好的 *.so / *.a 产物

  • Filament 模块拆分

    • filament-android
    • filament-utils-android
    • gltfio-android

这种方式虽然接入成本低,但在实际工程中逐渐暴露出几个问题。


2. 原有方案的痛点

(1)SO 体积偏大

Filament 官方 Android 产物以模块级 so形式存在:

  • 多个 so 文件
  • 每个 so 内部存在一定符号冗余
  • 无法针对 Sceneform-EQR 的真实使用场景裁剪

最终 APK / AAR 体积不友好


(2)Native 层不可控

  • 无法修改 JNI 注册逻辑
  • 无法裁剪不需要的 Native 功能
  • 排查 Native Crash 时,只能“对着黑盒猜”

(3)后续深度定制受限

随着 Sceneform-EQR 后续规划:

  • 自定义渲染管线
  • 深度接入 glTF / IBL / 视频纹理
  • 可能修改 Filament JNI 行为

故:必须依赖 Native 源码


3. 优化目标

综合考虑,最终确定本次优化目标:

  1. 引入 Filament JNI 源码
  2. 将 filament / utils / gltfio 三个模块合并为一个 so
  3. 统一 JNI_OnLoad,消除多 so 冲突
  4. 在不修改 Java API 的前提下,完成底层重构
  5. 降低 SO 体积,提升工程可维护性

二、准备阶段

1. 准备 Filament 源码

从官方仓库获取 Filament 源码:


2. 获取 Android Native 编译产物

有两种方式:

  • 方式一:自行编译 Filament

参考filament源码工程的build.md,按步骤操作即可获取

  • 方式二:直接使用官方 Release

当前推荐方式二,直接下载官方 Release 中的 android-native 产物:

https://github.com/google/filament/releases

解压后结构如下:

  • include/ → Filament 头文件
  • lib/arm64-v8a/*.a → 静态库


三、代码合并过程

1. Java 层代码合并

(1)覆盖 Filament Java API

当前 Sceneform-EQR 未修改 Filament Java 源码,因此可以直接覆盖:

com.google.android.filament.android.*

⚠️ 后续 Sceneform-EQR 将会对 Java API 有定制,需通过 Git 进行差异合并。


(2)合并三个 Android 模块的 Java 源码

将以下模块中的 src/main/java 内容合并至 Sceneform-EQR:

  • filament-android
  • filament-utils-android
  • gltfio-android


2. JNI 源码合并

(1)拷贝 filament-android JNI 源码

filament-1.67.1/android/filament-android/src/main/cpp

拷贝至:

Sceneform-eqr/cpp/filament-android


(2)同样处理 gltfio / filament-utils



3. 拷贝 common 代码

Filament JNI 依赖 common 层工具类:


拷贝至工程中


4. 拷贝 libs 与 third_party

从 Filament 源码中拷贝 必要的依赖库

实践建议: 只拷贝编译所需库,避免 third_party 全量引入


四、解决 JNI_OnLoad 冲突(核心问题)

1. 问题本质

官方 Filament:

  • filament-android.so
  • filament-utils.so
  • gltfio.so

!!!每个模块都有自己的 JNI_OnLoad!!!

而现在:

  • 需要 合并为一个 so
  • 只能存在一个 JNI_OnLoad

2. 解决思路

  • 各模块:

    • 移除 JNI_OnLoad
    • 提供 registerXXX() 方法
  • 核心 so:

    • 统一 JNI_OnLoad
    • 手动调用各模块注册函数

3. 修改 Filament.cpp

extern "C"
JNIEXPORT jint registerFilament(JavaVM* vm, void* reserved) {JNIEnv* env;if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {return -1;}::filament::VirtualMachineEnv::JNI_OnLoad(vm);return JNI_VERSION_1_6;
}

4. 修改 Utils.cpp(filament-utils)

extern "C"
JNIEXPORT jint registerUtils(JavaVM* vm, void*) {...env->RegisterNatives(...)return JNI_VERSION_1_6;
}

5. 重写统一 JNI_OnLoad

extern "C"
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {registerFilament(vm, nullptr);registerUtils(vm, nullptr);return JNI_VERSION_1_6;
}

五、Native 编译配置

1. 引入 Filament 静态库

将 android-native 产物引入工程:



2. CMakeLists 配置

  • filament-android
    跳转至git查看:
    https://github.com/eqgis/Sceneform-EQR/blob/dev-withFilamentCpp/Eq-Renderer/Android/eq-renderer/src/main/cpp/filament-android/CMakeLists.txt
  • gltfio-android
    跳转至git查看:
    https://github.com/eqgis/Sceneform-EQR/blob/dev-withFilamentCpp/Eq-Renderer/Android/eq-renderer/src/main/cpp/gltfio-android/CMakeLists.txt
  • filament-utils-android
    跳转至git查看:
    https://github.com/eqgis/Sceneform-EQR/blob/dev-withFilamentCpp/Eq-Renderer/Android/eq-renderer/src/main/cpp/filament-utils/CMakeLists.txt

!!!关键点:!!!

  • 使用 STATIC IMPORTED
  • 显式指定 .a 路径
  • 严格控制 target_link_libraries 顺序

3. 主模块 whole-archive

target_link_libraries(eqr-core-Wl,--whole-archivefilament-jnifilament-utils-jnigltfio-jni-Wl,--no-whole-archive
)

否则部分 JNI 符号会被裁剪


4. 头文件缺失问题

Filament 1.67.1 中:

  • backend/private 未包含在 android-native

解决方案:

从 Filament 源码工程补拷头文件

补充说明:当前需采用ndk 27以上版本


六、编译结果与优化收益

1. 最终 AAR 产物


2. SO 体积对比

方案 SO 大小
原多 so 方案 4.3 MB
合并 JNI 源码后 2.8 MB
  • 合并编译前
  • 合并编译后

体积减少约 35%


七、小结

本次优化带来的收益

  • SO 体积显著下降
  • Native 层完全可控
  • JNI 注册逻辑清晰统一
  • 为 Sceneform-EQR 后续深度定制打下基础

缺点:Sceneform-EQR升级filament的工作量增大,故以此文备忘~


http://www.jsqmd.com/news/139664/

相关文章:

  • 流量洪峰下的交通指挥家:详解负载均衡与限流实战
  • 团队推行敏捷开发两年,为何感觉效率不升反降?
  • 防水胶带正规厂商、品牌商、生产企业的全面解读与南通众皓推荐
  • 别再自己飞无人机了!这4个网站,高清航拍素材直接免费用!
  • 防水丁基胶带大型厂家及定制生产厂家的选购指南
  • 人工智能之数学基础 离散数学:第四章 离散概率
  • 探秘辉昂印刷厂的发展前景、技术实力
  • 探寻辉昂印刷厂:研发、排版与团队实力揭秘
  • Vue.js 中 Axios 的使用学习感悟与实践总结
  • 从ProfiNet转DeviceNet:看工业智能网关如何让伺服贴标机“即插即用”
  • Unity Collider 技术文档
  • redis为什么这么快?I/O多路复用技术是什么?
  • 万维易源与jmeter查询天气
  • DeviceNet转ProfiNet工业网关助力风机振动在线诊断
  • 国产操作系统下 Web 部署的实践与深度感悟
  • # 面试官冷笑:连GET和POST的区别都答不全?!(附避坑清单+实战案例)
  • CSDN 博文:《国产操作系统 KylinOS 实战:从安装到 Shell 脚本的 7 个核心技能》
  • 客服系统前端主题配色动态切换的一种实现思路(含代码)
  • http缓存
  • 2025造景石厂家推荐排行榜:从产能到质量全方位对比 - 爱采购寻源宝典
  • # 面试官冷笑:连301和302都分不清?这题我刷了3遍才敢去面试!(附状态码速记口诀)
  • 城市仿真软件:CityEngine_(1).CityEngine概述
  • 华为云 Flexus OBS:中小企业数据上云的“最优解”
  • 全球云基础设施支出增长,人工智能需求驱动市场扩张
  • 学长亲荐10个AI论文工具,继续教育论文写作必备!
  • Vue.js前端框架技术
  • 2025截止阀厂家推荐排行榜:从产能到质量权威解析 - 爱采购寻源宝典
  • 城市仿真软件:CityEngine_(2).城市建模基础
  • CSS Transform 导致 position:fixed 失效的排查与解决
  • 城市仿真软件:CityEngine_(4).数据导入与处理