This page looks best with JavaScript enabled

解决 Unity 2020 导出项目到 Android 中 So 加载问题

 ·  ☕ 1 min read

问题

Unity 项目将版本从 2018 升级到 2020 版本之后,导出集成到 Android 项目时,运行时报错找不到 libmain.so。

java.lang.UnsatisfiedLinkError: dlopen failed: library "/data/app/xxx/lib/arm/libmain.so" not found

原因

最终找到了根本原因:

Unity 2020 版导出的工程中 UnityPlayer 加载so 库用的是绝对路径方式,其源码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
String var6 = loadNative(getUnityNativeLibraryPath(var1));

private static String getUnityNativeLibraryPath(Context var0) {
    return var0.getApplicationInfo().nativeLibraryDir;
}

private static String loadNative(String var0) {
    String var1 = var0 + "/libmain.so";
    try {
        System.load(var1);
    } catch (UnsatisfiedLinkError var2) {
        return logLoadLibMainError(var1, var2.toString());
    } catch (SecurityException var3) {
        return logLoadLibMainError(var1, var3.toString());
    }
}

而我们 Android 项目用的 AGP(Android Gradle Plugin) 是 4.1 版本。AGP 3.6 版本之后增加了一项优化功能:AGP 编译时不再对共享库进行压缩操作,这样做会导致Apk变大,但是有另外两个好处:
• 减小应用安装大小,因为平台可以直接从已安装的 APK 访问原生库,而无需创建库的副本。也就是不再会把 so 拷贝到 nativeLibrary 路径里了。
• 减小下载文件大小,因为在 APK 或 Android App Bundle 中添加未压缩的原生库通常可提高 Google Play 商店的压缩率

所以在 nativeLibraryDir 中就不再会存放 Apk 中 so 的拷贝,而 UnityPlayer 却还是用原始路径去加载,就肯定会出现找不到文件的问题。

解决

在项目的 manifest.xml 中增加如下选项去关闭 AGP 的这项优化:

1
android:extractNativeLibs="true"

AGP 这个优化是好事,但是 Unity 团队可能没发现这个问题。


Yang
WRITTEN BY
Yang
Developer