VirtualAPK是滴滴出行自研的一款优秀的插件化框架
废话不多说,直接开撸
-
宿主工程
- 首先创建宿主工程,就是普通的工程,因为最近学习kotlin语言,所以demo都是基于kotlin编写的
- 在项目的build.gradle添加工程依赖
dependencies { classpath 'com.android.tools.build:gradle:2.3.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.didi.virtualapk:gradle:0.9.4' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } 复制代码
- 在app文件夹下build.gradle添加依赖
apply plugin: 'com.didi.virtualapk.host' compile 'com.didi.virtualapk:core:0.9.1' 复制代码
override fun onCreate() {
super.onCreate()
println("onCreate")
}
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
println("attachBaseContext")
PluginManager.getInstance(this)
.init()
}
}
复制代码
- 编写activity测试代码
简单来两个测试Button
先告一段落,现在去编写插件工程
-
插件工程
- 创建插件工程,同样是普通的工程
-
工程build.gradle添加 classpath 'com.didi.virtualapk:gradle:0.9.4'
dependencies { classpath 'com.android.tools.build:gradle:2.3.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.didi.virtualapk:gradle:0.9.4' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } 复制代码
-
app下的build.gradle添加 apply plugin: 'com.didi.virtualapk.plugin'
-
VirtualAPK 构建器
图中标注1的那个位置填写宿主项目app文件的文职,因为我的宿主项目和插件项目不再一个文件夹中,所以我使用的本地的绝对路径,大家到时候根据实际情况自己填写就行
``` virtualApk { // 插件资源表中的packageId,需要确保不同插件有不同的packageId. packageId = 0x6f // 宿主工程application模块的路径,插件的构建需要依赖这个路径 targetHost = '../../VirtualAPK/app' //默认为true,如果插件有引用宿主的类,那么这个选项可以使得插件和宿主保持混淆一致 applyHostMapping = true } 注:官方wiki说插件构建推荐使用Gradle 2.14.1版本,3.x版本可能有适配问题,我原来使用的gradle3.0.1版本没有构建过去,降到2.3.3以后OK 复制代码
这部分有什么疑问的请查阅官方wiki VirtualAPK README
- 插件工程配置完毕, 接下来就是打包插件
-
-
见证奇迹的时刻
-
把插件apk改名为Test.apk(我这是为了测试方便,正常情况名字随便起),然后push到手机的sd卡根目录(6.0以上的手机别忘了申请sd卡权限)
-
宿主工程activity添加三个个方法,还有点击事件
// 检查是否存在插件 private fun existsApk(): Boolean { val apk = File(Environment.getExternalStorageDirectory(), "Test.apk") return apk.exists() } // 加载插件 private fun loadPlugin(base: Context) { val pluginManager = PluginManager.getInstance(base) val apk = File(Environment.getExternalStorageDirectory(), "Test.apk") println("是否存在:" + apk) if (apk.exists()) { try { pluginManager.loadPlugin(apk) } catch (e: Exception) { e.printStackTrace() } } } // 跳转到插件的方法 private fun jump() { // 插件的包名 val pkg = "com.bidostar.virtualplugindemo" if (PluginManager.getInstance(this).getLoadedPlugin(pkg) == null) { Toast.makeText(this, "plugin [com.bidostar.virtualplugindemo] not loaded", Toast.LENGTH_SHORT).show() return } val intent = Intent() // 目标activity的全包名 intent.setClassName(this, "com.bidostar.virtualplugindemo.PluginActivity") startActivity(intent) } 复制代码
-
是骡子是马,拉出来溜溜
-
后记
1. 实际编写过程中遇到了很多的问题
* VirtualAPK 构建器配置不正确,尤其是宿主工程目录targetHost配置不正确无法正确加载
* 插件工程activity名字和布局文件名字和宿主工程有重名的,也无法加载插件apk
* 6.0手机没有申请SD卡权限,造成无法加载插件apk
* ...
所以编写的时候还是要细心一点,官方文档先看一遍,注意一些细节的部分
复制代码