带so库的apk正确内置到system/app详解
序:目前有个项目,以前不带so的时候可以内置嵌入到/system/app下面,现在接入so就遇到一启动就奔溃的问题,下面我来详细说说怎么解开这个问题的吧。
先说原因
产生的日志(apk的包名为com.dangbeiaddemo)
java.lang.UnsatisfiedLinkError: Couldn't load dbasdpi from loader dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.dangbeiaddemo-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.dangbeiaddemo-1, /vendor/lib, /system/lib]]]: findLibrary returned null
根据日志的反馈,我去查看了下System.loadLibrary的源码看到一行
所以肉戏来了,关键点就在loader.findLibrary()
看了半天源码和资料,ClassLoader的那个findLibrary()实际上会在两个部分的文件夹中去寻找System.loadLibrary()要load的那个library,一个部分是,构造ClassLoader时,传进来的那个library path,另外一个部分是system property。在android系统中,查找要load的library,实际上会在nativeLibraryDirectories=[/data/app-lib/com.dangbeiaddemo-1, /vendor/lib, /system/lib]中查询。
我们通过log查看可以知道:loader为PathClassLoader,find的文件夹路径为[DexPathList[[zip file "/data/app/com.dangbeiaddemo-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.dangbeiaddemo-1, /vendor/lib, /system/lib]]]
注意:不同的手机不同的版本可能路基稍微有点不一样
所以就是一开始通过root 权限将apk直接push到/system/app目录下,导致启动无法加载so文件奔溃
解决方案
所以分多步入手:
1.尽量能加载出来so,下面这个方法在某些机型可用
System.load(context.getDir("lib", 0).getParentFile().getAbsolutePath());
2.不能加载出来,我给它拷贝进去
当你push 一个apk到/system/app文件夹下面的时候,你可以push so文件到/system/lib文件下面,这样就可以正常运行了。
3.需要捕获异常才能进行二次调用。
正常情况下,第一次调用就会抛出UnsatisfiedLinkError,你需要try catch这个异常。一开始我是用Exception去捕获的,所以直接奔溃,下图为异常结构图:
4.实在无法加载的,必须要在代码里做处理,不调用native方法
参考链接: