You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 10+如何运行动态模块中打包为共享库的可执行文件?

Android动态模块中运行重命名为SO的GCC工具链权限被拒问题解决

问题背景

我开发的Android平台IDE集成了多套面向不同MCU的GCC工具链SDK,为绕开Google Play的AAB 200MB体积限制,将每个SDK单独打包为动态模块:把工具链的可执行文件重命名为共享库格式(例如xtensa-esp32-elf-g++改名为libesp32_xtensa-esp32-elf-g++.so),放在动态模块的jniLibs/arm64-v8a目录,其余文件作为资源打包。

原本在Android 10+系统中,主APK/AAB内的这类共享库可以通过创建符号链接到可执行目录正常运行,但动态模块安装后,文件路径为/data/user/0/%package%/files/splitcompat/7900/native-libraries/esp32_sdk.config.arm64_v8a/libesp32_xtensa-esp32-elf-g++.so,尝试在context.filesDir下创建符号链接并执行时,触发error=13,权限被拒绝异常。将文件复制到codeCacheDir、cacheDir、filesDir目录后执行,同样报错。主APK中放置同类文件则可正常运行,但会大幅增加包体积,且预加载用户可能不需要的SDK,不符合需求。测试覆盖Android 16模拟器及多台Android 10+实体设备。

问题原因

  1. 动态模块splitcompat目录下的原生库文件,系统未自动设置执行权限,而主APK的原生库在安装阶段会被系统处理权限,因此可正常执行。
  2. 复制文件到应用私有目录时,仅复制了文件内容,未手动设置可执行权限,导致文件无法被执行。

解决方案

1. 复制文件后手动设置可执行权限

优先选择codeCacheDir存放可执行文件,该目录是系统专为应用可执行文件设计的,权限管控更适配。复制完成后,通过代码设置文件的执行权限:

// 从动态模块获取源文件路径
String sourcePath = "/data/user/0/%package%/files/splitcompat/7900/native-libraries/esp32_sdk.config.arm64_v8a/libesp32_xtensa-esp32-elf-g++.so";
File sourceFile = new File(sourcePath);

// 目标文件存放在codeCacheDir,恢复原可执行文件名
File targetFile = new File(context.getCodeCacheDir(), "xtensa-esp32-elf-g++");

// 复制文件内容
try (InputStream in = new FileInputStream(sourceFile);
     OutputStream out = new FileOutputStream(targetFile)) {
    byte[] buffer = new byte[1024];
    int length;
    while ((length = in.read(buffer)) > 0) {
        out.write(buffer, 0, length);
    }
} catch (IOException e) {
    e.printStackTrace();
}

// 设置可执行权限
targetFile.setExecutable(true, false); // false表示仅应用所有者拥有执行权限,更安全

// 执行文件
try {
    Process process = new ProcessBuilder(targetFile.getAbsolutePath())
            .redirectErrorStream(true)
            .start();
    // 处理进程输出等逻辑
} catch (IOException e) {
    e.printStackTrace();
}

2. 避免使用符号链接

动态模块原文件本身无执行权限,符号链接仅指向原文件,无法解决权限问题。直接复制文件到可写目录并设置权限是更可靠的方案。

3. 动态模块打包配置优化

在动态模块的build.gradle中添加配置,防止系统自动压缩或剥离工具链文件的符号信息:

android {
    packagingOptions {
        doNotStrip "*/libesp32_xtensa-esp32-elf-g++.so"
        exclude "lib/arm64-v8a/libesp32_xtensa-esp32-elf-g++.so.gz"
    }
}

内容的提问来源于stack exchange,提问作者4ntoine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 10:36:07