最近遇到这样一个问题:
第三方的SDK除了Jar包外,还提供了对应的so文件。
APK集成SDK后进行测试,发现一切正常。
但将APK作为系统应用集成到ROM时,发现so获取失败。
看了一下SDK的代码,发现由于底层库的需求,SDK没有直接利用System.loadLibrary来加载so,
而是主动获取so的路径,对应的代码如下:
protected static String findNativeLibraryPath(Context context, String libraryName) {
if (context == null) {
return null;
}
if (TextUtils.isEmpty(libraryName)) {
return null;
}
String dexPath = context.getPackageCodePath();
//注意这个地方
//取的是ApplicationInfo中的nativeLibraryDir
String nativeLibraryDir = context.getApplicationInfo().nativeLibraryDir;
//创建PathClassLoader
PathClassLoader pathClassLoader = new PathClassLoader(dexPath, nativeLibraryDir,
ClassLoader.getSystemClassLoader());
//利用PathClassLoader来获取so的路径
return pathClassLoader.findLibrary(libraryName);
}
为了解释这个问题及寻找解决方案,我们就必须查找对应的源码了。
接下来,我们就以8.0的代码为例,看看相应的流程。
一、PathClassLoader相关内容
我们先来看看PathClassLoader相关的源码:
public class PathClassLoader extends BaseDexClassLoader {
...........
//前文传入ApplicationInfo的nativeLibraryDir
//对应此处的librarySearchPath
public PathClassLoader(String dexPath, String librarySearchPath, ClassLoader parent) {
super(dexPath, null, librarySearchPath, parent);
}
}
PathClassLoader继承BaseDexClassLoader,仅实现了两个构造函数,
主要的逻辑还是实现于BaseDexClassLoader中。
1.1 BaseDexClassLoader相关内容
我们来看看BaseDexClassLoader中的代码:
public class BaseDexClassLoader extends ClassLoader {
.............
public BaseDexClassLoader(String dexPath, File optimizedDirectory,
String librarySearchPath, ClassLoader parent) {
super(parent);
//注意这里构造了DexPathList, 同样传入了librarySearchPath
this.pathList = new DexPathList(this, dexPath, librarySearchPath, null);
.................
}
...........
@Override
public String findLibrary(String name) {
return pathList.findLibrary(name);
}
.......
}
从代码不难发现,findLibrary查找的实际上是DexPathList,
后者于BaseDexClassLoader的构造函数中创建。
1.2 DexPathList相关内容
继续跟进DexPathList对应的代码:
final class DexPathList {
...