Skip to content

Instantly share code, notes, and snippets.

@ownwell
Created August 24, 2017 01:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ownwell/a7eb09586b0da9361a9d98437fdca369 to your computer and use it in GitHub Desktop.
Save ownwell/a7eb09586b0da9361a9d98437fdca369 to your computer and use it in GitHub Desktop.
动态加载so
package com.baidu.common.sofile;
import android.content.Context;
import android.os.Build;
import com.baidu.common.LogUtil;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class LoadNativeLibraryUtils {
private static final String TAG = "LoadNativeLibraryUtils";
public static final String SO_CACHE_DIR = "jniLibs";
public static void injectDir(Context context) {
File dir = context.getDir(SO_CACHE_DIR, Context.MODE_PRIVATE);
ClassLoader classLoader = context.getApplicationContext().getClassLoader();
try {
installNativeLibraryPath(classLoader, dir);
} catch (Throwable throwable) {
// ignore
}
}
private static void installNativeLibraryPath(ClassLoader classLoader, File folder)
throws Throwable {
if (folder == null || !folder.exists()) {
LogUtil.e(TAG, "installNativeLibraryPath, folder:" + folder + " is illegal");
return;
}
// android o sdk_int 26
// for android o preview sdk_int 25
if ((Build.VERSION.SDK_INT == 25 && Build.VERSION.PREVIEW_SDK_INT != 0)
|| Build.VERSION.SDK_INT > 25) {
try {
V25.install(classLoader, folder);
return;
} catch (Throwable throwable) {
// install fail, try to treat it as v23
// some preview N version may go here
LogUtil.e(TAG, "installNativeLibraryPath, v25 fail, sdk:" + Build.VERSION.SDK_INT + " , error:" +
throwable.getMessage());
V23.install(classLoader, folder);
}
} else if (Build.VERSION.SDK_INT >= 23) {
try {
V23.install(classLoader, folder);
} catch (Throwable throwable) {
// install fail, try to treat it as v14
LogUtil.e(TAG,
"installNativeLibraryPath, v23 fail, sdk:" + Build.VERSION.SDK_INT + " , error:" + throwable
.getMessage());
V14.install(classLoader, folder);
}
} else if (Build.VERSION.SDK_INT >= 14) {
V14.install(classLoader, folder);
} else {
V4.install(classLoader, folder);
}
}
private static final class V4 {
private static void install(ClassLoader classLoader, File folder) throws Throwable {
String addPath = folder.getPath();
Field pathField = ReflectUtil.findField(classLoader, "libPath");
StringBuilder libPath = new StringBuilder((String) pathField.get(classLoader));
libPath.append(':').append(addPath);
pathField.set(classLoader, libPath.toString());
Field libraryPathElementsFiled = ReflectUtil.findField(classLoader, "libraryPathElements");
List<String> libraryPathElements = (List<String>) libraryPathElementsFiled.get(classLoader);
libraryPathElements.add(0, addPath);
libraryPathElementsFiled.set(classLoader, libraryPathElements);
}
}
private static final class V14 {
private static void install(ClassLoader classLoader, File folder) throws Throwable {
Field pathListField = ReflectUtil.findField(classLoader, "pathList");
Object dexPathList = pathListField.get(classLoader);
ReflectUtil.expandFieldArray(dexPathList, "nativeLibraryDirectories", new File[] {folder});
}
}
private static final class V23 {
private static void install(ClassLoader classLoader, File folder) throws Throwable {
Field pathListField = ReflectUtil.findField(classLoader, "pathList");
Object dexPathList = pathListField.get(classLoader);
Field nativeLibraryDirectories = ReflectUtil.findField(dexPathList, "nativeLibraryDirectories");
List<File> libDirs = (List<File>) nativeLibraryDirectories.get(dexPathList);
libDirs.add(0, folder);
Field systemNativeLibraryDirectories =
ReflectUtil.findField(dexPathList, "systemNativeLibraryDirectories");
List<File> systemLibDirs = (List<File>) systemNativeLibraryDirectories.get(dexPathList);
Method makePathElements =
ReflectUtil.findMethod(dexPathList, "makePathElements", List.class, File.class, List.class);
ArrayList<IOException> suppressedExceptions = new ArrayList<>();
libDirs.addAll(systemLibDirs);
Object[] elements = (Object[]) makePathElements.
invoke(dexPathList, libDirs, null, suppressedExceptions);
Field nativeLibraryPathElements = ReflectUtil.findField(dexPathList, "nativeLibraryPathElements");
nativeLibraryPathElements.setAccessible(true);
nativeLibraryPathElements.set(dexPathList, elements);
}
}
private static final class V25 {
private static void install(ClassLoader classLoader, File folder) throws Throwable {
Field pathListField = ReflectUtil.findField(classLoader, "pathList");
Object dexPathList = pathListField.get(classLoader);
Field nativeLibraryDirectories = ReflectUtil.findField(dexPathList, "nativeLibraryDirectories");
List<File> libDirs = (List<File>) nativeLibraryDirectories.get(dexPathList);
libDirs.add(0, folder);
Field systemNativeLibraryDirectories =
ReflectUtil.findField(dexPathList, "systemNativeLibraryDirectories");
List<File> systemLibDirs = (List<File>) systemNativeLibraryDirectories.get(dexPathList);
Method makePathElements =
ReflectUtil.findMethod(dexPathList, "makePathElements", List.class);
libDirs.addAll(systemLibDirs);
Object[] elements = (Object[]) makePathElements.
invoke(dexPathList, libDirs);
Field nativeLibraryPathElements = ReflectUtil.findField(dexPathList, "nativeLibraryPathElements");
nativeLibraryPathElements.setAccessible(true);
nativeLibraryPathElements.set(dexPathList, elements);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment