我通过以下方式加载本机库:
try {
System.loadLibrary("myNative");
} catch (UnsatisfiedLinkError e) {
//java.lang.UnsatisfiedLinkError here
System.load("/data/data/com.my.app/app_native/libmyNative.so");
}
上面的代码最终被打包到一个Jar文件中。
在另一个项目中,我用DexClassLoader加载了上面的Jar :
DexClassLoader dexClassLoader = new DexClassLoader(jarPath,
optJarPath,
getDir("native", Context.MODE_PRIVATE),
getClassLoader());
请注意,构造此dexClassLoader
实例时,我指定了本机代码所在的路径,即getDir("native", Context.MODE_PRIVATE)
。
(我正在使用NDK版本10生成本机库。生成本机代码文件libmyNative.so时,我的Java代码(打包到最终的Jar中)检查CPU架构类型并将正确的代码复制到getDir("native", Context.MODE_PRIVATE)
。)
上面的代码在Android 5.0 Lollipop以外的其他设备上都可以正常工作。在Android 5.0 Lollipop设备上运行时,我不断收到以下错误:
java.lang.UnsatisfiedLinkError: dlopen failed: "/data/data/com.my.app/app_native/libmyNative.so" is 32-bit instead of 64-bit
at java.lang.Runtime.load(Runtime.java:331)
at java.lang.System.load(System.java:982)
如何解决这个问题呢?
您似乎正在尝试在64位目标上使用32位库。如果您无法提供64位版本,则必须说服Android退回到32位模式以容纳该库。
显然,兼容性模式(源似乎将其称为ABI覆盖)通常是在安装时设置的,安装程序会发现只有32位(而非64位)库可用。但是在您的情况下,该库在安装时不可见,因此无法正常工作。
如果您在apk中放置了一个“虚拟” 32位库,它与64位设备的需求最为匹配,则系统希望将您的应用配置为以32位兼容模式运行,以便以后加载真正的32位位库将实际工作。
我不知道32位库是否需要是真正的库,而不是具有正确位置和合理名称的空文件,但是ndk示例文件夹libhello-jni.so的hello-jni项目应该可以工作。您不需要任何相应的Java代码,只需拥有安装程序可以发现的本机库即可(但是,将其作为测试调用可能不是一个坏主意)。
可能有其他方法可以触发此操作,例如清单中的某些内容(尽管文档中未提及)。我不太可能怀疑运行时的任何措施都会起作用,因为在任何代码运行之前可能已经牢固设置了该模式(看起来您实际上可能最终在这种系统上运行了两个zygote实例,一个64位,另一个32位,其想法是认为任何合适的应用都可以启动应用)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句