为 arm64 Android 手机构建应用程序包时在 ApplicationInfo.nativeLibraryDir 中找不到本机库
Posted
技术标签:
【中文标题】为 arm64 Android 手机构建应用程序包时在 ApplicationInfo.nativeLibraryDir 中找不到本机库【英文标题】:Native libraries not found in ApplicationInfo.nativeLibraryDir when building app bundle for arm64 Android phone 【发布时间】:2019-10-26 07:24:51 【问题描述】:我正在尝试将我的应用从单一 APK 迁移到 app bundle 格式。我需要为exec()
调用设置LD_LIBRARY_PATH
环境变量,因此我需要本地库的位置。使用原始 APK 我会调用 getApplicationInfo().nativeLibDir
并且库就在那里。
对于应用程序包,它们不是。 我可以看到安装了正确的 abi split APK,但由于某种原因,这些库没有被提取。
我已尝试使用bundletool
并通过 Google Play 安装,
尝试运行'ls -alR'
,我可以清楚地看到目录存在以及拆分的apk,但库根本没有被提取。我想我可以手动提取它们作为一种解决方法,但这似乎没有必要..?
这是ls
在nativeLibPath
的父文件夹上的输出
genLibraryPath: Dir Contents: /data/app/com.unseenonline-raAFLhJMQpjqWkVdG1Vocg==:
total 16704
drwxr-xr-x 4 system system 4096 2019-06-11 12:41 .
drwxrwx--x 114 system system 12288 2019-06-11 12:41 ..
-rw-r--r-- 1 system system 5688352 2019-06-11 12:41 base.apk
drwxr-xr-x 3 system system 4096 2019-06-11 12:41 lib
drwxrwx--x 3 system install 4096 2019-06-11 12:41 oat
-rw-r--r-- 1 system system 11226112 2019-06-11 12:41 split_config.arm64_v8a.apk
-rw-r--r-- 1 system system 35636 2019-06-11 12:41 split_config.en.apk
-rw-r--r-- 1 system system 90443 2019-06-11 12:41 split_config.xxhdpi.apk
/data/app/com.unseenonline-raAFLhJMQpjqWkVdG1Vocg==/lib:
total 24
drwxr-xr-x 3 system system 4096 2019-06-11 12:41 .
drwxr-xr-x 4 system system 4096 2019-06-11 12:41 ..
drwxr-xr-x 2 system system 4096 2019-06-11 12:41 arm64
/data/app/com.unseenonline-raAFLhJMQpjqWkVdG1Vocg==/lib/arm64:
total 16
drwxr-xr-x 2 system system 4096 2019-06-11 12:41 .
drwxr-xr-x 3 system system 4096 2019-06-11 12:41 ..
如您所见,拆分后的 apk 存在,但未提取库。
应将库提取到与原始 apk 相同的位置
【问题讨论】:
【参考方案1】:默认情况下,从 android App Bundle 生成的 APK 在 Android M / API 级别 23 或更高级别 (source) 的设备上具有未压缩的原生库。这不仅通常会减少下载大小,而且还会大大减少设备上应用程序的大小,因为 Android 平台可以直接从 APK 读取本机库,而不必将它们提取到单独的位置。上次 I/O 大会上有一个关于如何减小应用大小以及它如何影响安装数量的演讲,如果您有兴趣更好地了解这一点,他们详细说明了这是如何工作的。
所以,既然您知道 Google Play 这样做的原因,那么您有以下选择:
您可以选择恢复到原始 APK 行为,这可以通过在 gradle.properties 文件中添加标志 android.bundle.enableUncompressedNativeLibs=false
来完成。这将有效地禁用此优化,从而为 M+ 上的所有用户带来更大的应用程序尺寸。
如果原生库由您所依赖的第三方库加载,请考虑为他们提交错误以解决此问题,以便它们遵循与平台相同的逻辑。
希望对你有帮助,
【讨论】:
感谢您的回答。是否有一些标准方法可以从 apk 获取本机库的字节偏移量?我假设谷歌希望我们使用System.loadLibrary()
,但是使用共享库的二进制文件呢?现在完全不支持了吗?
要在您的 APK 中查找共享库,您可以使用 AssetManager.openNonAssetFd()。而不是 dlopen(),您应该使用特定于平台的android_dlopen_ext(),并传递 AssetFileDescriptor 的句柄和偏移量。请注意,AssetManager 也有 native API。
相信你也可以做到dlopen("/path/to/MyApp.apk!libfoo.so", ...)
。如果这不起作用,您可以提交一个错误吗?我们应该确保有一个简单的方法来做到这一点(我认为应该有一个 API 只是“从我的 APK 打开这个库”,所以你不需要找出你的 APK 的路径...文件如果你想要的话,一个错误要求 API)
@DanAlbert 根据this answer,您可以从java 调用System.loadLibrary()
,然后dlsym(0,..)
将适用于任何加载的库。不确定这是否适用于使用exec()
生成的进程或仅适用于 JNI 调用。您也可以尝试从您的本机代码中调用loadLibrary()
java 命令。
@EladLevin,感谢您分享我的答案。不错的好处是System.loadLibrary()
可以透明地与未提取的库一起使用。不幸的是,这些库不能与衍生的可执行文件共享。以上是关于为 arm64 Android 手机构建应用程序包时在 ApplicationInfo.nativeLibraryDir 中找不到本机库的主要内容,如果未能解决你的问题,请参考以下文章
为 arm64-v8a 构建 libtensorflow_cc.so 问题
Android 安装包优化动态库打包配置 ( “armeabi-v7a“, “arm64-v8a“, “x86“, “x86_64“ APK 打包 CPU 指令集配置 | NDK 完整配置参考 )(代