Virtual APK 入坑
一.为什么选择VirtualAPK
1.插件开发等同于开发原生 APK,无需做特定的处理
2.宿主和插件之间有耦合形态和独立两种关系,耦合形态时插件对宿主有代码和资源的依赖;独立形态时插件对宿主无任何依赖关系
3.市场兼容性良好,经过了滴滴的实际检验
![VA系统架构图](https://img-blog.csdn.net/20170817153429519?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hyaXNtYTY2Ng==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
二.接入流程{以 demo 工程为例说明}
1.宿主工程 project.gradle文件中添加 classPath:
classpath 'com.didi.virtualapk:gradle:0.9.0'
2.宿主工程 app.gradle 文件中引用 VA 插件:
apply plugin: 'com.didi.virtualapk.host'
3.宿主工程 app.gradle 文件中依赖 VA 插件:
compile 'com.didi.virtualapk:core:0.9.0'
4.插件工程 project.gradle 文件中添加 classpath:
classpath 'com.didi.virtualapk:gradle:0.9.0'
5.插件工程 app.gradle 文件中引用 VA插件
compile 'com.didi.virtualapk:core:0.9.0'
apply plugin: 'com.didi.virtualapk.plugin'
(选配)可以配置自定义的构建变体:
productFlavors {
beijing {
applicationId 'com.didi.virtualapk.demo'
}
shanghai {
applicationId 'com.didi.virtualapk.demo'
}
}
6.在插件中配置宿主信息
virtualApk {
//指定插件资源表中的packageId,不同的插件不能相同{打包时宿主和插件资源会合并,所以不能重复}
packageId = 0x6f
//指定插件的宿主工程模块的相对路径{一般宿主工程只有一个 app 模块}
targetHost = '../../VirtualAPK-master/app'
//设置宿主和插件的混淆规则是否保持一致,默认为 true
applyHostMapping = true
}
三.运行流程{以 demo 工程为例说明}
1.先运行宿主工程,安装到设备上,运行之后会生成宿主工程的版本信息{versions.txt}和资源id{Host_R.txt}
![宿主运行后版本信息](https://img-blog.csdn.net/20170817153540117?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hyaXNtYTY2Ng==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
2.编译插件:
a.terminal 中切换到插件工程根路径
./gradlew assemblePlugin
{此处不能运行./gradlew assembleRelease 或者 ./gradlew assembleDebug --》 java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity}
3.push 插件
adb push app/build/outputs/apk/app-beijing-release-unsigned.apk /sdcard/Test.apk {这里可以选择不同的构建遍体进行 push}
4.在宿主中加载插件
4.1 宿主模块Application 类中初始化 VA
@override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
PluginManager.getInstance(base).init();
}
4.2 加载插件
PluginManager pluginManager = PluginManager.getInstance(base);
File apk = new File(Environment.getExternalStorageDirectory(), "Test.apk");
if (apk.exists()) {
try {
pluginManager.loadPlugin(apk);
} catch (Exception e) {
e.printStackTrace();
}
}
4.3跳转到插件
Intent intent = new Intent();
intent.setClassName("com.didi.virtualapk.demo", "com.didi.virtualapk.demo.aidl.BookManagerActivity");
startActivity(intent);
{插件的寻找以包名为唯一 id,不能直接指定 this,this 指的是插件本身引用}