Android動態載入so檔案

來源:互聯網
上載者:User

標籤:android   style   blog   http   io   ar   os   sp   檔案   

在Android中調用動態庫檔案(*.so)都是通過jni的方式,而且往往在apk或jar包中調用so檔案時,都要將對應so檔案打包進apk或jar包,工程目錄:

以上方式的存在的問題:

1、缺少靈活性比較類似靜態載入了(不是靜態載入),能載入的so檔案綁定死了;

2、但so檔案很多或很大時,會導致對應的apk和jar包很大;

3、不能動態對so檔案更新;

 

Android中載入so檔案的提供的API:

void System.load(String pathName);

說明:

1、pathName:檔案名稱+檔案路勁;

2、該方法調用成功後so檔案中的匯出函數都將插入的系統提供的一個映射表(類型Map);

 

看到以上對System.load(String pathName);的函數說明可定有人會想到將so檔案放到一個指定的目錄然後再通過參數pathName直接引用該目錄的路勁和對應的so檔案問題不就解決了嗎?

這裡有個問題被忽略了,那就是System.load只能載入兩個目錄路勁下的so檔案:

1、/system/lib ;

2、安裝包的路勁,即:/data/data/<packagename>/…

而且這兩個路勁又是有許可權保護的不能直接存取;

 

問題解決方案:

先從網路下載so檔案到手機目錄(如:/test/device/test.so) –> 將test.so載入到記憶體(ByteArrayOutputStream) –> 然後儲存到對用安裝包目錄;

具體代碼如下:

try {
            String localPath = Environment.getExternalStorageDirectory() + path;
            Log.v(TAG, "LazyBandingLib localPath:" + localPath);

            String[] tokens = mPatterns.split(path);
            if (null == tokens || tokens.length <= 0
                    || tokens[tokens.length - 1] == "") {
                Log.v(TAG, "非法的檔案路徑!");
                return -3;
            }
            // 開闢一個輸入資料流
            File inFile = new File(localPath);
            // 判斷需載入的檔案是否存在
            if (!inFile.exists()) {
                // 下載遠程驅動檔案
                Log.v(TAG, inFile.getAbsolutePath() + " is not fond!");
                return 1;
            }
            FileInputStream fis = new FileInputStream(inFile);

            File dir = context.getDir("libs", Context.MODE_PRIVATE);
            // 擷取驅動檔案輸出資料流
            File soFile = new File(dir, tokens[tokens.length - 1]);
            if (!soFile.exists()) {
                Log.v(TAG, "### " + soFile.getAbsolutePath() + " is not exists");
                FileOutputStream fos = new FileOutputStream(soFile);
                Log.v(TAG, "FileOutputStream:" + fos.toString() + ",tokens:"
                        + tokens[tokens.length - 1]);

                // 位元組數組輸出資料流,寫入到記憶體中(ram)
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int len = -1;
                while ((len = fis.read(buffer)) != -1) {
                    baos.write(buffer, 0, len);
                }
                // 從記憶體到寫入到具體檔案
                fos.write(baos.toByteArray());
                // 關閉檔案流
                baos.close();
                fos.close();
            }
            fis.close();
            Log.v(TAG, "### System.load start");
            // 載入外設驅動
            System.load(soFile.getAbsolutePath());
            Log.v(TAG, "### System.load End");

            return 0;

        } catch (Exception e) {
            Log.v(TAG, "Exception   " + e.getMessage());
            e.printStackTrace();
            return -1;

}

Android動態載入so檔案

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.