Android中如何動態引入so庫


動態引入so庫

為什么要動態引入so庫?

遇到的問題:因為要做一些系統級別的工具,所以要調用一些系統的so庫,如果把so庫直接放在lib目錄下的話,在android程序啟動的時候會默認加載lib目錄下的所有庫,但是這些so庫會在一些地方存在沖突,所以為了解決這個沖突的問題,就使用動態加載so庫的方式,通過一些條件的判斷是否要加載這個so庫。

如何動態加載so庫?

1.首先把so庫放在assets資源目錄下,一般會放兩個so庫,一個32位一個64位的
2.動態加載,就是在需要使用的時候,從assets資源目錄下復制到app-libs目錄下
public static boolean loadLibrary(Context context, String oldFileName, String libName) throws IOException {
        // 獲取應用的私有模式的libs目錄(真實的目錄是app-libs)
        File libs_dir = context.getDir("libs", Context.MODE_PRIVATE);
	    // 可以獲取到assets資源文件的數據流
        InputStream open = context.getAssets().open(oldFileName);
        String new_file_name = libs_dir.getPath() + "/" + libName;
		// 把資源文件的數據流寫入到app-libs目錄下
        if (!copyLibrary(open, new_file_name)) {
            return false;
        }
        try {
            System.load(new_file_name);
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }

        return true;
    }
//從assets資源目錄下復制到app-libs目錄下
    public static boolean copyLibrary(InputStream fileInputStream, String new_file) {

        FileOutputStream fos = null;
        try {

            File file = new File(new_file);
            fos = new FileOutputStream(file);
            int     dataSize;
            byte[]  dataBuffer = new byte[2048];

            while ((dataSize = fileInputStream.read(dataBuffer)) != -1) {
                fos.write(dataBuffer, 0, dataSize);
            }
            fos.flush();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("NativeLibraryLoader",e.getMessage());
        } finally {
            try {
                if (fos != null) fos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return false;
    }
3.判斷系統是多少位的然后在靜態代碼塊里加載不同的so庫
static {
        //注冊
        try {
            Context context = MainApplication.getContextObject();
            String osName = "lib32.so";
            //如果這個SUPPORTED_ABIS包含64就是64位的系統
            if (SUPPORTED_ABIS[0].contains("64")) {
                osName = "lib64.so";
            }
            NativeLibraryLoader.loadLibrary(context, osName, "libtv.so");
        } catch (Exception e) {
            e.printStackTrace();
        }
   }
4.存在問題

在沒有關閉selinux的情況下,System.load(xxxx.so)會因為權限的原因導致失敗 Permission denied;

如果權限夠的話,可以直接使用暴力的方法,直接把assert目錄的文件直接復制到lib目錄下,然后使用System.loadLibrary(libsitatv.so)就能直接加載


免責聲明!

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



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