ACDD使用教程

Thu 01 October 2015

ACDD使用教程

ACDD项目原名为OpenAtlas, taobao的Android客户端使用的动态部署(插件化)方案。

获取ACDD

git clone https://github.com/jiangfengbing/ACDD.git
git clone https://github.com/jiangfengbing/ACDDExtension.git

我的仓库是从bunnyblue的github fork来的,在开发分支有我修正bug的commit

ACDD的仓库包含两个项目:

  • ACDDCore: ACDD的核心库
  • ACDDLauncher: 加载插件的宿主APP

ACDDExtension的仓库包含的内容:

  • 插件资源分组架构图: Architecture/images/Architecture.001.jpg
  • 编译好的demo: Dist/ACDDLauncher.apk
  • 插件demo: Samples
  • 针对机型的测试报告: TestReport
  • 编译: buildTools
  • aapt: 修改过的appt, 增加对versionName的处理
  • ACDDExt: 处理插件apk,生成bundle-info.json

使用ACDD

替换aapt

ACDDExtension中修改过的appt复制到sdk的编译工具目录(如:/opt/Android/android-sdk-macosx/build-tools/22.0.1)下

插件的开发

以application的形式正常开发,插件不依赖ACDDCore库

apply plugin: 'com.android.application'

插件的versionName在正常的赋值后面需要加上插件ID,ID的范围是:0x10 - 0x7e,最多111个插件。

如:

android {
    defaultConfig {
        versionName "1.00x11"
        ...
    }
...
}

注意:多个插件间的ID不能重复

build.gradle里面指定buildTools的版本

android {
    ...
    buildToolsVersion "22.0.1"
    ...
}

宿主的开发

宿主需要依赖ACDDCore库:

dependencies {
    compile project(':ACDDCore')
}

最简单的使用方法:宿主Application从ACDDApp继承。

将插件AndroidManifest.xml里面声明的组件和权限,在宿主的AndroidManifest.xml里面再次声明,name需要使用绝对className。

宿主自带插件的部署的方法:

ACDDExt.jar处理插件apk,生成so文件(还是apk文件)和bundle-info.json,将so文件放在libs/armeabi目录下面,将bundle-info.json放到assets目录下面

自带的方法可以参照ACDDLauncherbuild.gradle脚本

可以不将so放在libs/armeabi目录,而又宿主动态安装插件,方法如下:

try {
    String location = "com.ijinshan.ShouJiKong.AndroidDaemon";
    File file = new File("/sdcard/libcom_ijinshan_ShouJiKong_AndroidDaemon.so");
    ACDD.getInstance().installBundle(location, new FileInputStream(file));
} catch (Exception e) {
    e.printStackTrace();
}

ACDD的限制

官方维护的已知问题列表: https://github.com/bunnyblue/ACDD/issues/1

绕不开的限制:插件的资源ID仅在容器内部有效,如果将插件的资源用于和系统交互,系统是从宿主apk里面找不到资源的。实际限制表现在:

  • 不能弹使用插件图标的通知
  • 插件的Activity切换动画

解决方法: 相关的资源放到宿主里面去,这些可以使用public.xml定义

举例:插件需要使用slide_left_in, slide_left_out, slide_right_in, slide_right_out几种Activity切换动画

  • 将插件的res/anim/slide_left_in.xml, res/anim/slide_left_out.xml, res/anim/slide_right_in.xml, res/anim/slide_right_out.xml复制到宿主下面
  • 在宿主的res/values/public.xml文件里面加入资源ID的赋值。
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <public type="anim" name="slide_left_in" id="0x7f040000" />
    <public type="anim" name="slide_left_out" id="0x7f040001" />
    <public type="anim" name="slide_right_in" id="0x7f040002" />
    <public type="anim" name="slide_right_out" id="0x7f040003" />
</resources>
  • 将插件里面切换动画的资源ID改为宿主public.xml里面定义的值
//overridePendingTransition(R.anim.slide_right_in, R.anim.slide_right_out);
overridePendingTransition(0x7f040002, 0x7f040003);

PS: 如果想把layout里面的id固定除了在public.xml里面加入:

<public type="id" name="tv_progress" id="0x7f..." />

外,还需要在res/values/ids.xml里面加入:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <item type="id" name="tv_progress" />
</resources>

注意: 在public.xml里面如果你将0x7f04....用于一种资源类型(如: anim),那给其他类型(如: drawable)将不能再使用0x7f04...., 可以使用0x7f05...

错误处理

  • 因为运行容器和真实环境的差异,有些异常信息的输出比较隐蔽或者不准确。如果手机界面黑屏,基本上可以判断出问题了。

  • 出问题后,先看宿主进程的日志输出,如果没有相关的错误信息,请看全部的日志输出,这个时候可能是外部找不到插件内的资源。

  • 如果出现某个插件内的类找不到,而插件已经实例化(Application已经onCreate过), 那么有可能是这个类的第三方基类没有编译进插件,可以考虑将基类的包编译进宿主APP。

Category: Android Tagged: Android 插件化

Comments