外掛化知識梳理(5) Small 框架之如何不將外掛打包到宿主中

澤毛發表於2017-12-21

一、前言

在前面的例子當中,我們都是把外掛預置在Apk當中一起安裝的,如 外掛化知識梳理(4) - Small 框架之如何實現外掛更新 所示,我們初始時候會將代表外掛的so檔案放置在jniLibs/armeabi目錄下。

外掛化知識梳理(5)   Small 框架之如何不將外掛打包到宿主中
那麼如果我們將不是很重要的外掛放在伺服器上,當應用啟動之後判斷需要該外掛,然後再從伺服器上下載,將能夠有效減小初始時候安裝包的體積。

下面,我們就來演示一下如何從外部載入外掛。

二、示例

載入外掛部分的原始碼位於Bundle.java中:

外掛化知識梳理(5)   Small 框架之如何不將外掛打包到宿主中
可以看到,載入外掛有兩種方式,它們是根據Small.isLoadFromAssets來區分:

  • 如果該標誌位為真,那麼讀取/data/data/{host_pkg_name}/small_base/下的外掛,並且包名和外掛的對應關係為:pkg_name -> {pkg_name}.apk
  • 如果該標誌位為假,那麼讀取nativeLibraryDir目錄下的so,並且包名和外掛的對應關係為:pkg_name -> lib{pkg_name}.so,也就是我們之前一直演示的方式。

通過這段原始碼,那麼如何實現載入外部外掛就有思路了:

  • 刪除調jniLIbs/armeabi下的so檔案
  • 通過Small.setLoadFromAssets方法將標誌位設為true
  • 從網路上獲取外掛,建立/data/data/{host_pkg_name}/small_base/{pkg_name}.apk,通過檔案流的形式將下載下來的外掛寫入到.apk當中。

這裡因為沒有伺服器,所以我們把預先編譯好的外掛.so檔案拷貝到外部儲存中,從外部儲存讀取的過程就相當於是網路下載的過程:

    private void initPlug() {
        //表明需要從外部載入外掛。
        Small.setLoadFromAssets(true);
        try {
            File dstFile = new File(FileUtils.getInternalBundlePath(), "com.demo.small.update.app.upgrade.apk");
            if (!dstFile.exists()) {
                dstFile.createNewFile();
            }
            File srcFile = new File(Environment.getExternalStorageDirectory().toString() + "/Small/" + "libcom_demo_small_update_app_upgrade.so");
            FileInputStream inputStream = new FileInputStream(srcFile);
            OutputStream outputStream = new FileOutputStream(dstFile);
            byte[] buffer = new byte[1024];
            int length;
            //將.so的內容寫入到.apk當中。
            while ((length = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, length);
            }
            outputStream.flush();
            outputStream.close();
            inputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
複製程式碼

更多文章,歡迎訪問我的 Android 知識梳理系列:

相關文章