Created
August 24, 2017 01:53
-
-
Save ownwell/a7eb09586b0da9361a9d98437fdca369 to your computer and use it in GitHub Desktop.
动态加载so
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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