VirtualAPK 调研结果

##1 插件化

>一般定义是:对现有的程序添加额外的功能组件

通俗理解:加载外部APK

##2 这样的优势

+ 国内App的版本碎片较为严重,减少升级成本。

+ 解决App方法数超65536问题。在谷歌官方的Multidex方案没有出现时,可以采用插件方式解决:

+ 减少App包大小。宿主App包含了主要功能,其余放到插件中实现,动态下发;

+ 模块解耦,协同开发。一个超级App,可以拆分成不同的插件模块,基于一定的规则业务线之间协同开发,最终每个业务模块生成一个插件,由宿主加载组合即可。

##VirtualAPK

https://github.com/didi/VirtualAPK

是滴滴的开源插件话框架 请读者详细阅读一下Readme和Wiki,对VirtualAPK框架有个整体的认识

VirtualAPK是滴滴出行自研的一款优秀的插件化框架,主要有如下几个特性。

##VirtualAPK特性

###功能完备

+ 支持几乎所有的Android特性;

+ 四大组件方面

####四大组件均不需要在宿主manifest中预注册,每个组件都有完整的生命周期。

1. Activity:支持显示和隐式调用,支持Activity的 theme 和 LaunchMode ,支持透明主题;

2. Service:支持显示和隐式调用,支持Service的 start 、 stop 、 bind 和 unbind ,并支持跨进程bind插件中的Service;

3. Receiver:支持静态注册和动态注册的Receiver;

4. ContentProvider:支持provider的所有操作,包括 CRUD 和 call 方法等,支持跨进程访问插件中的Provider。

+ 自定义View:支持 自定义View ,支持自定义属性和 style ,支持动画;

+ PendingIntent:支持 PendingIntent 以及和其相关的 Alarm 、 Notification 和 AppWidget ;

+ 支持插件 Application 以及插件manifest中的 meta-data ;

+ 支持插件中的 so 。

####优秀的兼容性

+ 兼容市面上几乎所有的Android手机,这一点已经在滴滴出行客户端中得到验证;

+ 资源方面适配小米、Vivo、Nubia等,对未知机型采用自适应适配方案;

+ 极少的Binder Hook,目前仅仅hook了两个Binder: AMS 和 IContentProvider ,hook过程做了充分的兼容性适配;

+ 插件运行逻辑和宿主隔离,确保框架的任何问题都不会影响宿主的正常运行。

####入侵性极低

+ 插件开发等同于原生开发,四大组件无需继承特定的基类;

+ 精简的插件包,插件可以依赖宿主中的代码和资源,也可以不依赖;

+ 插件的构建过程简单,通过Gradle插件来完成插件的构建,整个过程对开发者透明。

####Wiki中和已有的插件话框架的对比

特性        | DynamicLoadApk| DynamicAPK|Small|DroidPlugin|VirtualAPK

-----------|:-------------:| :---------:|:---:|:--------:|:--------:

支持四大组件 | 只支持Activity| 只支持Activity|只支持Activity|全支持| 全支持

组件无需在宿主manifest中预注册 | √| × |×      | √        | √       

插件可以依赖宿主  | √ | √ |√      |    ×    |√       

支持PendingIntent| × |× |× |√| √

Android特性支持 |大部分 |大部分| 大部分| 几乎全部 |几乎全部

兼容性适配| 一般 |一般 |中等 |高| 高

插件构建 |无 |部署aapt| Gradle插件 |无| Gradle插件

####VirtualAPK接入指南

>Gradle版本号目前需要为2.14.1

com.android.tools.build的版本号为2.1.3

>宿主接入:

1. 在宿主工程根目录的build.gradle添加依赖

```java

dependencies {

classpath 'com.didi.virtualapk:gradle:0.9.0'

}

```

2. 在App的工程模块的build.gradle添加使用gradle插件

```java

apply plugin: 'com.didi.virtualapk.host'

```

3. 添加VirtualAPK SDK compile依赖

```java

dependencies {

compile 'com.didi.virtualapk:core:0.9.0'

}

```

4. 在App的工程模块proguard-rules.pro文件添加混淆规则(Ps:Picasso库的混淆规则没有列出来)

```java

-keep class com.didi.virtualapk.internal.VAInstrumentation { *; }

-keep class com.didi.virtualapk.internal.PluginContentResolver { *; }

-dontwarn com.didi.virtualapk.**

-dontwarn android.content.pm.**

-keep class android.** { *; }

```

5. MyApplication类是继承了Application,覆写attachBaseContext函数,进行插件SDK初始化工作

```java

@Override

protected void attachBaseContext(Context base)  {

  super.attachBaseContext(base);

  PluginManager.getInstance(base).init();

}

```

6. 在使用插件之前加载插件,可以根据具体业务场景选择合适时机加载,我是在MainActivity的onCreate时机加载

```java

protected void onCreate(Bundle savedInstanceState) {

      // 加载plugin.apk插件包

    PluginManager pluginManager = PluginManager.getInstance(this);

    File apk = new File(getExternalStorageDirectory(), "plugin.apk");

    if (apk.exists()) {

        try {

            pluginManager.loadPlugin(apk);

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

}

```

经过上述6步后,VirtualAPK插件功能就集成到宿主中了,宿主打包和运行方式没有任何改变。接下来看下插件工程如何集成和构建的。

>插件工程接入

1. 插件工程根目录的build.gradle添加依赖

```java

dependencies {

classpath 'com.didi.virtualapk:gradle:0.9.0'

}

```

2. 在App的工程模块的build.gradle添加使用gradle插件和插件配置信息,信息需要放在文件最下面

```java

apply plugin: 'com.didi.virtualapk.plugin'

...

...

// 插件配置信息,放在文件最下面

virtualApk {

packageId = 0x6f            // 插件资源id,避免资源id冲突

targetHost='../host/app'      // 宿主工程的路径

applyHostMapping = true      // 插件编译时是否启用应用宿主的apply mapping

}

```

>解释一下上面3个参数的作用

+ packageId用于定义每个插件的资源id,多个插件间的资源Id前缀要不同,避免资源合并时产生冲突

+ targetHost指明宿主工程的应用模块,插件编译时需要获取宿主的一些信息,比如mapping文件、依赖的SDK版本信息、R资源文件,一定不能填错,否则在编译插件时会提示找不到宿主工程。

+ applyHostMapping表示插件是否开启apply mapping功能。当宿主开启混淆时,一般情况下插件就要开启applyHostMapping功能。因为宿主混淆后函数名可能有fun()变为a(),插件使用宿主混淆后的mapping映射来编译插件包,这样插件调用fun()时实际调用的是a(),才能找到正确的函数调用。

3. 最后一步生成插件,需要使用Gradle命令

```java

gradle clean assemblePlugin

```

或者

```java

./gradlew clean assemblePlugin

```

资料来源:

1. 接入指南

http://www.jianshu.com/p/013510c19391

2. 源码分析

http://blog.csdn.net/lmj623565791/article/details/75000580

http://blog.csdn.net/u012124438/article/details/74118905   

你可能感兴趣的:(VirtualAPK 调研结果)