android loadlibrary 更改libPath 路徑,指定路徑加載.so


http://www.jianshu.com/p/f751be55d1fb

字數549 閱讀177 評論0 
  • 需求很簡單 ,就是加載指定文件夾下的.so。
  • 原因:android在程序運行的狀態下 ,無法在 data/data/packageName/lib 下寫文件,但可讀。
  • 還有一個引申的問題:data/app-lib/packageName/ 下的.so 和 data/data/packageName/lib 的.so 是什么關系

1 . 獲取全局的classloader

PathClassLoader pathClassLoader = (PathClassLoader)context.getClassLoader();
DexClassLoader myDexClassLoader = new DexClassLoader(str, context.getDir("dex", 0).getAbsolutePath(), str, context.getClassLoader().getParent());

2 . 獲取pathList

Object pathList = getPathList(pathClassLoader);

3 . 添加路徑

File[] file = new File[]{ new File("/data/app-lib/pakageName-1"), new File("/data/app-lib/pakageName-2"), new File("/data/data/pakageName/files"), new File("/vendor/lib"), new File("/system/lib") } ;

4 . 獲取當前類的屬性

Object nativeLibraryDirectories=pathList.getClass().getDeclaredField("nativeLibraryDirectories"); ((Field)nativeLibraryDirectories).setAccessible(true);

5 . 設置新的路徑

((Field)nativeLibraryDirectories).set(pathList, file);

6 . 對classloader的操作,對應於BaseDexClassLoader:

public BaseDexClassLoader(String dexPath,File optimizedDirectory,String libraryPath,ClassLoader parent){ super(parent); this.pathList=new DexPathList(this,dexPath,libraryPath,optimizedDirectory); }

7 . dex,library路徑對應於DexPathList, 這部分和熱補丁密切相關,有興趣可以搜下hotfix ,很多開源項目。

privatefinalElement[]dexElements;  //這部分就是dex分包的了,熱補丁,熱補丁,熱補丁 privatefinalFile[]nativeLibraryDirectories;//這部分就是 libs 加載路徑了,默認有 /vendor/lib system/lib data/app-lib/packageName

最后給下代碼:

    public static void initNativeDirectory(Application application) { if (hasDexClassLoader()) { try { createNewNativeDir(application); } catch (Exception e) { e.printStackTrace(); } } } private static void createNewNativeDir(Context context) throws Exception{ PathClassLoader pathClassLoader = (PathClassLoader) context.getClassLoader(); Object pathList = getPathList(pathClassLoader); //獲取當前類的屬性 Object nativeLibraryDirectories = pathList.getClass().getDeclaredField("nativeLibraryDirectories"); ((Field) nativeLibraryDirectories).setAccessible(true); //獲取 DEXPATHList中的屬性值 File[] files1 = (File[])((Field) nativeLibraryDirectories).get(pathList); Object filesss = Array.newInstance(File.class, files1.length + 1); //添加自定義.so路徑 Array.set(filesss, 0, new File(context.getFilesDir().getAbsolutePath())); //將系統自己的追加上 for(int i = 1;i<files1.length+1;i++){ Array.set(filesss,i,files1[i-1]); } // File[] filesss = new File[file.length+ files1.length]; // filesss[0] = file[0]; // for(int i = 1;i < files1.length+1;i++){ // filesss[i] = files1[i]; // } ((Field) nativeLibraryDirectories).set(pathList, filesss); } private static Object getPathList(Object obj) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { return getField(obj, Class.forName("dalvik.system.BaseDexClassLoader"), "pathList"); } private static Object getField(Object obj, Class cls, String str) throws NoSuchFieldException, IllegalAccessException { Field declaredField = cls.getDeclaredField(str); declaredField.setAccessible(true); return declaredField.get(obj); } /** * 僅對4.0以上做支持 * @return */ private static boolean hasDexClassLoader() { try { Class.forName("dalvik.system.BaseDexClassLoader"); return true; } catch (ClassNotFoundException var1) { return false; } }

參考鏈接


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM