我有两个应用程序A和B。apps使用DexClassLoader
从应用程序B加载一个自定义视图类。
但是,如果应用程序B中的自定义视图加载私有本地库,则通过java.lang.System.loadLibrary
和dalvik.system.PathClassLoader
与apk捆绑在一起。然后我得到
java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.example.app-b-xxx==/base.apk"],nativeLibraryDirectories=[/system/lib, /vendor/lib]]] couldn't find "my_native_lib.so"
如果我自己启动应用程序B,它就能够加载私有的本地库了。
这有支持吗?我知道DexClassLoader
只加载类,但是这些加载的类能够调用它们自己绑定的本地库吗?
发布于 2022-03-21 00:07:25
你真的不应该像这样直接加载类,你可能会因此而惹上谷歌的麻烦。我相信这是对戏剧商店的TOS的反对。这也是不安全的--如果安装了其他同名的应用程序,假装是你,你就允许他们的代码以你的用户身份运行,这是一个巨大的安全问题。
但让我们忽略这一点。这就是它不能工作的原因--你的应用程序没有那个库。当您通过loadLibrary加载时,它正在查找一个特定的路径,该路径是应用程序本地的.so文件。在这个上下文中,“您的应用程序”是正在运行的应用程序,而不是代码来自的应用程序。所以它找错地方了。如果在这两个应用程序中都包含了.so文件,它可能会起作用。但是您显然需要知道实现细节才能使其工作,您不能使用它来加载任意类的库。
发布于 2022-05-27 11:15:16
如果您愿意使用一些反射,DexClassLoader
包含一个名为pathList
的私有字段,该字段包含一个名为addNativePath(Collection)
的方法。
要获得App的本机库目录,您可以通过包管理器加载它。
// assumes currently in an activity
val nativeLibraryPath = packageManager.getPackageInfo("com.package.name", 0).applicationInfo.nativeLibraryDir
val clClass = classLoader.javaClass
val plField = clClass.superclass.getDeclaredField("pathList")
plField.isAccessible = true
val plInst = plField.get(classLoader)
val plClass = plClass.javaClass
val anpMethod = plClass.getDeclaredMethod("addNativePath", Collection::class.java)
anpMethod.invoke(
plInst,
listOf(nativeLibraryPath)
)
请记住,由于使用了隐藏的API方法,这可能会在某些较新版本的Android中停止工作。(我编写的代码主要是在Android 11上测试的)
如果您使用System.loadLibrary
加载本机库(基于所提供的错误似乎不是这种情况),那么只使用带有从App到本机库的绝对路径的System.load
就可以工作,而无需使用类加载器。
https://stackoverflow.com/questions/71551268
复制相似问题