news 2026/5/23 18:57:14

RK3399E 部署 APK 到系统分区

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
RK3399E 部署 APK 到系统分区

1. 部署 APK 到系统分区

将应用放入 /system/priv-app 会使其自动成为“特权系统应用”,从而获得访问系统内部库的权限。

1.1操作步骤:

adb root adb disable-verity # 针对 RK3399 固件,通常需要关闭校验才能修改 /system adb reboot # 重启以生效 adb root adb remount # 重新挂载分区为可读写


1.2 推送 APK:

# 创建存放目录(建议与应用包名一致) adb shell mkdir -p /system/priv-app/xxxApp # 将编译好的 APK 推送进去 adb push YourApp-release.apk /system/priv-app/xxxApp/xxxApp.apk

1.3 设置权限(关键):

adb shell chmod 755 /system/priv-app/xxxApp adb shell chmod 644 /system/priv-app/xxxApp/xxxApp.apk adb shell chown root:root /system/priv-app/xxxApp/xxxApp.apk

2. 实现加载系统 librosa.so

仅仅把 APK 放进系统是不够的,Android 11 的 Linker Namespace(链接器命名空间) 依然会拦截对非标准库的加载。

2.1 配置白名单:

修改 /system/etc/public.libraries.txt,在文件末尾添加一行(不要带路径)

libxxx.so

注:这告诉系统,librosa.so 是一个允许被 App 加载的公共库。

2.2 放置系统库(如果你还没放):

adb push librosa.so /system/lib64/ adb shell chmod 644 /system/lib64/libxxx.so

2.3 修复 SELinux 标签(最重要的一步):

如果你不执行这一步,App 会因为 SELinux 拦截报错 permission denied。

adb shell restorecon /system/lib64/libxxx.so adb shell restorecon /system/etc/public.libraries.txt adb shell restorecon -R /system/priv-app/xxxApp

2.4 重启系统:

adb reboot

3 错误解决

3.1 重启后会出现以下错误:

现在的错误是 React Native 层面的 JS 加载失败:

java.lang.RuntimeException: Unable to load script. Make sure you're either running Metro (run 'npx react-native start') or that your bundle 'index.android.bundle' is packaged correctly for release.

为什么会出现这个错误?

当你将 APK 放入 /system/priv-app 时,它脱离了开发环境(Metro Server)。系统应用必须是 Release 模式,并且必须在 APK 内部包含离线资源包(index.android.bundle)。

你的日志显示:

App 尝试连接 localhost:8081(Metro 调试服务器)失败。

App 转向读取 assets/index.android.bundle,但在 APK 内没找到这个文件。

3.2 解决方案

1. 确保构建的是 Release 版本

你不能直接把 Debug 版的 APK 放入 /system。请在项目根目录运行:

# 如果使用 Expo npx expo export:embed --platform android --dev false --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res
# 然后通过 Gradle 构建 Release APK cd android ./gradlew assembleRelease

构建完成后,APK 路径通常在:android/app/build/outputs/apk/release/app-release.apk。


2. 检查 APK 是否包含 Bundle 文件(关键手动检查)

在推送 APK 到系统之前,请在电脑上检查该 APK 内部, 将 app-release.apk 后缀改为 .zip 并打开。确认是否存在 assets/index.android.bundle 文件。如果没有这个文件,App 永远无法作为系统应用启动。

3. 重新执行以下步骤

adb root adb remount # 删除旧的测试包 adb shell rm -rf /system/priv-app/xxxApp # 创建目录并推送正式 Release 包 adb shell mkdir -p /system/priv-app/xxxApp adb push android/app/build/outputs/apk/release/app-release.apk /system/priv-app/xxxApp/xxxApp.apk # 设置权限 adb shell chmod 755 /system/priv-app/xxxApp adb shell chmod 644 /system/priv-app/xxxApp/xxxApp.apk adb shell restorecon -R /system/priv-app/xxxApp # 重启 adb reboot

4. APP打包时排除so库

步骤 1:修改 CMakeLists.txt(核心配置)

JSI 模块的 CMake 配置是关键,需要移除本地 SO 的导入,仅保留符号链接,让编译器知道从系统目录查找 SO。

原 JSI 模块 CMakeLists.txt(内置 SO 示例)
cmake_minimum_required(VERSION 3.13) # 导入本地 SO(原逻辑) add_library(libtest SHARED IMPORTED) set_target_properties(libtest PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libtest.so ) # JSI 模块编译 add_library( jsi-test-module # JSI 模块名 SHARED ./cpp/JSIExample.cpp # JSI 绑定的 C++ 代码 ) # 链接本地 SO(原逻辑) target_link_libraries( jsi-test-module libtest # 本地 SO reactnativejsi # RN JSI 核心库 log android )

修改后的 CMakeLists.txt(系统 SO 配置)

cmake_minimum_required(VERSION 3.13) # 关键1:移除本地 SO 的 add_library 和 IMPORTED_LOCATION 配置 # 关键2:添加系统库搜索路径(指向 Android 系统 SO 目录) link_directories( /system/lib64 # 64位系统 SO 路径(32位写 /system/lib) /vendor/lib64 # 可选:vendor 分区的 SO 路径 ) # JSI 模块编译(保留原有 JSI 绑定代码) add_library( jsi-test-module SHARED ./cpp/JSIExample.cpp ) # 关键3:链接时直接指定系统 SO 名(去掉 lib 前缀),不关联本地文件 target_link_libraries( jsi-test-module test # 系统 SO:对应 /system/lib64/libtest.so(仅写 test,系统自动补全 lib 和 .so) reactnativejsi # RN JSI 核心库(必须保留) log android ) # 关键4:设置链接选项,强制从系统路径加载 SO(避免优先找 APK 内置) target_link_options( jsi-test-module PRIVATE -Wl,-rpath=/system/lib64 # 指定运行时 SO 搜索路径 -Wl,--enable-new-dtags # 启用新的动态标签,确保 rpath 生效 )
步骤 2:修改 build.gradle(排除 SO 打包)

确保 Gradle 不会将目标 SO 打包到 APK 中,避免与系统 SO 冲突(和 JNI 场景一致,但必须配置):

android { // ... 其他配置(compileSdk、buildToolsVersion 等) defaultConfig { // ... externalNativeBuild { cmake { arguments "-DANDROID_STL=c++_shared" // 保持与系统 SO 一致的 STL abiFilters "arm64-v8a" // 仅保留系统 SO 对应的架构(如 arm64-v8a) } } } // 排除目标 SO 打包到 APK packagingOptions { exclude 'lib/arm64-v8a/libtest.so' // 64位 SO exclude 'lib/armeabi-v7a/libtest.so' // 32位 SO(如果有) } sourceSets { main { jniLibs.srcDirs = ['src/main/jniLibs'] jniLibs.exclude "**/libtest.so" // 双重保障:排除所有 ABI 的 libtest.so } } externalNativeBuild { cmake { path "src/main/cpp/CMakeLists.txt" // 指向修改后的 CMake 文件 } } }
步骤 3:修改 C++ 代码(显式加载系统 SO,可选但推荐)

JSI 模块加载时,需确保系统 SO 已被加载(避免符号未找到错误)。在 JSI 绑定的入口函数前,手动加载系统 SO:

void forceLoadSystemRosaSO() { void* handle = dlopen("libtest.so", RTLD_NOW); if (!handle) { // 如果失败,查看 dlerror() throw std::runtime_error(dlerror()); } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/20 5:52:15

语音文件存储策略:临时缓存与持久化权衡

语音文件存储策略:临时缓存与持久化权衡 📌 背景与问题引入 在构建基于 Sambert-Hifigan 的中文多情感语音合成服务时,一个常被忽视但至关重要的工程问题是:如何管理生成的语音文件? 尤其是在集成了 Flask WebUI 和 AP…

作者头像 李华
网站建设 2026/5/19 21:53:00

AI如何用VALUECELL优化Excel数据处理

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 开发一个基于AI的Excel数据处理工具,利用VALUECELL功能自动识别和优化数据格式,支持数据清洗、公式生成和可视化分析。工具应包含以下功能:1. 自…

作者头像 李华
网站建设 2026/5/20 12:18:40

Llama Factory微调大全:从单轮到多轮对话优化

Llama Factory微调大全:从单轮到多轮对话优化 如果你正在开发对话系统,想要优化Llama模型的多轮对话能力却苦于缺乏经验,这篇文章将为你提供一个全面的实操指南。Llama Factory作为一款强大的微调工具,能够帮助开发者从简单的单轮…

作者头像 李华
网站建设 2026/5/1 8:35:37

1小时搞定原型:Cursor Free VIP快速开发指南

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 开发一个快速原型制作工具,功能包括:1. 自然语言描述转代码功能;2. 常用组件库一键插入;3. 实时预览和修改;4. 多设备适…

作者头像 李华
网站建设 2026/5/11 18:12:28

开源TTS模型哪家强?Sambert-Hifigan中文多情感合成自然度评分第一

开源TTS模型哪家强?Sambert-Hifigan中文多情感合成自然度评分第一 🎯 选型背景:中文多情感语音合成的技术演进与挑战 近年来,随着智能客服、有声读物、虚拟主播等应用场景的爆发式增长,高质量中文语音合成(…

作者头像 李华
网站建设 2026/5/1 8:35:43

蓝易云 - 如何使用CORS来允许设置Cookie

下面这篇内容直击核心,从浏览器安全模型出发,系统性讲清楚 如何通过 CORS 正确允许设置 Cookie,不兜圈子、不堆概念,适合真实生产环境直接落地。 一、为什么“跨域请求能成功,但 Cookie 却没带上?”&#x…

作者头像 李华