SDK 開發使用 VirtualAPK 實現外掛化

Keven發表於2019-04-17

1. 背景

因為公司現在要在廣告 SDK 開發中實現一部分程式碼的更新,或者是新增部分功能,因此需要從後臺通過網路下載然後通過外掛化的方式進行載入展示。本來想的是自己實現,但是遇到了一些問題,所以直接採用滴滴的開源框架 VirtualAPK 來實現。由於 VirtualAPK 是針對於 app 開發者的,所以我們在打包的時候需要把 SDK 稍微做一些改動。

2. 前期準備

滴滴開源框架 VirtualAPK 的 GitHub 地址為 github.com/didi/Virtua… Wiki 的內容可以瞭解框架整合及使用。如果想了解原理則可以閱讀原始碼進行了解。

3. 專案結構

SDK 開發使用 VirtualAPK 實現外掛化

1. 宿主結構

內部有 HostMainActivity、HostMyApp 兩個類

  1. HostMainActivity 用於外掛載入和跳轉外掛中的頁面
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
    String pluginPath = Environment.getExternalStorageDirectory().getAbsolutePath().concat("/testpulgin.apk");
    File plugin = new File(pluginPath);
    try {
            PluginManager.getInstance(getApplicationContext()).loadPlugin(plugin);
        } catch (Exception e) {
            e.printStackTrace();
    }
} else {
    ActivityCompat.requestPermissions(this,
        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100);
        }
    TextView tv_host = findViewById(R.id.tv_host);
    tv_host.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent();
            intent.setClassName("keven.zcdog.pluginvirtual", "keven.zcdog.pluginvirtual.PluginMainActivity");
            startActivity(intent);
        }
});
複製程式碼
  1. HostMyApp 用於主 APP 進行呼叫初始化 VirtualAPK
public class HostMyApp  {
    public static void init(Context context){
        PluginManager.getInstance(context).init();
    }
}
複製程式碼

2. 外掛結構

外掛中就只有一個 Activity 和一個佈局,供宿主呼叫。

4. 專案搭建

1. 專案配置

根據 GitHub 上的配置進行專案配置

  1. 在根目錄的 build.gradle 檔案中新增
classpath 'com.didi.virtualapk:gradle:0.9.8.6'
複製程式碼

在根目錄的 gradle.properties 檔案中新增

android.useDexArchive=false
複製程式碼
  1. 在宿主的 build.gradle 檔案中新增
apply plugin: 'com.didi.virtualapk.host'
複製程式碼
compile 'com.didi.virtualapk:core:0.9.8'
複製程式碼
  1. 在外掛專案的根目錄 build.gradle 檔案中新增(由於我這邊外掛和宿主在同一專案中,所以只需要配置一次即可)
classpath 'com.didi.virtualapk:gradle:0.9.8.6'
複製程式碼
  1. 在外掛的 build.gradle 檔案中新增
apply plugin: 'com.didi.virtualapk.plugin'
複製程式碼
virtualApk {
    packageId = 0x62  // 為了避免資源衝突.
    targetHost='D:/AndroidDemo/RetryVirtualApk/myaarhost' // 宿主專案位置,最好配置絕對路徑,避免出錯.
    applyHostMapping = true      // 預設為 true.
}
複製程式碼

2. 生成外掛包

先在 myaarhost 的 build.gradle 檔案中進行修改

將
apply plugin: 'com.android.library'
替換為
apply plugin: 'com.android.application'
複製程式碼

然後點選 Android Studio 右側工具欄對宿主進行 build

SDK 開發使用 VirtualAPK 實現外掛化

然後點選外掛專案的 按鈕生成外掛 apk

SDK 開發使用 VirtualAPK 實現外掛化

如果可以成功,可以在外掛專案中找到(由於生成的是 release 包,所以需要配置下簽名)

SDK 開發使用 VirtualAPK 實現外掛化

如果過程中報錯,可參考 VirtualAPK 踩坑實錄 ,我當時就是借鑑這篇文章的一些解決方法解決的。

5. 測試

  1. 將 myaarhost 改回 library,然後生成 aar
  2. 將產生的外掛 apk 放入到手機根目錄
  3. 新建專案,依賴 aar 包
  4. 在新建專案根目錄配置
classpath 'com.didi.virtualapk:gradle:0.9.8.6'
複製程式碼

在新建專案 app 下配置

compile 'com.didi.virtualapk:core:0.9.8'
複製程式碼
  1. 新建類繼承 Application ,呼叫 aar 中的方法初始化 VirtualAPK
public class MyApplication extends Application {
    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        HostMyApp.init(base);
    }
}
複製程式碼
  1. 啟動 aar 中的 Activity
Intent intent = new Intent(MainActivity.this, HostMainActivity.class);
startActivity(intent);
複製程式碼
  1. 實現效果

SDK 開發使用 VirtualAPK 實現外掛化

6. 全部程式碼

本文所有程式碼見 GitHub 地址
github.com/keven0632/V…

相關文章