原因:如果把so文件直接放在libs目录下,在android程序启动的时候会默认加载libs目录下的所有so库,但这些so库可能会在某些地方存在冲突,使用动态加载so库,就可以通过一些条件判断是否要加载这个so库。
 介绍:so的动态加载是把so库打包成apk的时候剔除,在合适的时候通过网络包下载的方式,在运行的时候进行分离加载。
 优点:so文件是动态加载的,不是绑定死的,更便于修改,在so库有问题的时候可以动态更新;
 so库文件动态加载可以极大地减小apk包的体积;
 解决多个第三方库文件同时加载可能出现冲突的问题。
    public static void load(String filename) {         Runtime.getRuntime().load0(Reflection.getCallerClass(), filename);     }         public static void loadLibrary(String libname) {         Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname);     }     public static Runtime getRuntime() {         return currentRuntime;     }     private synchronized void loadLibrary0(ClassLoader loader, Class<?> callerClass, String libname) {         if (libname.indexOf((int)File.separatorChar) != -1) {             throw new UnsatisfiedLinkError(     "Directory separator should not appear in library name: " + libname);         }         String libraryName = libname;         //ClassLoader不为空时(程序中通过System.loadlibrary()方式,这个loader就不会为空)         if (loader != null && !(loader instanceof BootClassLoader)) {         //通过ClassLoader的findLibrary方法查找so的文件名称,寻找so文件是否存在             String filename = loader.findLibrary(libraryName);             //判断,如果未找到so文件,并且类加载器存在             if (filename == null &&                     (loader.getClass() == PathClassLoader.class ||                      loader.getClass() == DelegateLastClassLoader.class)) {                 filename = System.mapLibraryName(libraryName);//拼接so文件名             }             if (filename == null) {                 throw new UnsatisfiedLinkError(loader + " couldn't find \"" +                                                System.mapLibraryName(libraryName) + "\"");             }             //so文件存在,加载它             String error = nativeLoad(filename, loader);             if (error != null) {             //加载异常,加载失败                 throw new UnsatisfiedLinkError(error);             }             return;         }         //ClassLoader为空时,传入library name和System.mapLibraryName获得真正的library name。         //具体深入的实现过程,可以到Android源码继续查看getLibPaths()和mapLibraryName的实现         getLibPaths();         String filename = System.mapLibraryName(libraryName);//mapLibraryName用于拼接so文件名的前缀:lib和后缀.so         //例如传入的是wudong,得到的就会是libwudong.so,然后在mLibPaths查找'libwudong.so',最终确定library的path。         String error = nativeLoad(filename, loader, callerClass);         if (error != null) {//加载异常             throw new UnsatisfiedLinkError(error);         }     } 1.首先把so库放在assets资源目录下,一般会放两个so库,一个32位一个64位的;
 2.动态加载,就是在需要使用的时候,从assets资源目录下复制到app/libs目录下;
 3.通过 System.load(String filename) 或者 System.loadLibrary(String libname) 方法去加载 so。
 ·在so原本的加载过程中,是系统通过ClassLoader检索native目录里是否存在so库进行加载的,那就需要把下载存放so的路径添加到ClassLoader的libs路径里,这些libs路径在app启动的时候就已经生成了,那就需要利用反射,在运行时把路径添加进去。
利用反射将存放so的路径放到ClassLoader中,开源项目tinker的TinkerLoadLibrary也有实现发方法,我们就不用自己实现了,可以拿过来直接使用。
private static final class V25 {         private static void install(ClassLoader classLoader, File folder)  throws Throwable {             final Field pathListField = ShareReflectUtil.findField(classLoader, "pathList");             final Object dexPathList = pathListField.get(classLoader);              final Field nativeLibraryDirectories = ShareReflectUtil.findField(dexPathList, "nativeLibraryDirectories");              List<File> origLibDirs = (List<File>) nativeLibraryDirectories.get(dexPathList);             if (origLibDirs == null) {                 origLibDirs = new ArrayList<>(2);             }             final Iterator<File> libDirIt = origLibDirs.iterator();             while (libDirIt.hasNext()) {                 final File libDir = libDirIt.next();                 if (folder.equals(libDir)) {                     libDirIt.remove();                     break;                 }             }             origLibDirs.add(0, folder);              final Field systemNativeLibraryDirectories = ShareReflectUtil.findField(dexPathList, "systemNativeLibraryDirectories");             List<File> origSystemLibDirs = (List<File>) systemNativeLibraryDirectories.get(dexPathList);             if (origSystemLibDirs == null) {                 origSystemLibDirs = new ArrayList<>(2);             }              final List<File> newLibDirs = new ArrayList<>(origLibDirs.size() + origSystemLibDirs.size() + 1);             newLibDirs.addAll(origLibDirs);             newLibDirs.addAll(origSystemLibDirs);              final Method makeElements = ShareReflectUtil.findMethod(dexPathList, "makePathElements", List.class);              final Object[] elements = (Object[]) makeElements.invoke(dexPathList, newLibDirs);              final Field nativeLibraryPathElements = ShareReflectUtil.findField(dexPathList, "nativeLibraryPathElements");             nativeLibraryPathElements.set(dexPathList, elements);         }     } } 这样路径就可以添加进ClassLoader的nativeLibraryDirectories中了。