不久前看到这篇文章《[酷狗 Android App 插件化实施过程][a067ea5c]》,但是这里并没有相关实现的细节,其中提到的DroidPlugin、dynamic-load-apk,在此前也曾经了解过,都存在不少的问题。
最近和在酷狗工作的朋友聊天的时候谈到这个,才得知酷狗实际应用的是Small框架.
由于第一次听说这个框架,第一时间到github上了解了解。Small For Android
由于github上的文档能说明的内容不多,一些问题还是只能跳进坑中去游一游。还在
- 使用Small进行Android模块化开发
- 轻量级插件化框架——Small
- Android插件化(使用Small框架)
这几篇文章跨越了两个版本,第一个是V0.1.1,我就分别做了一下测试。
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.0'
classpath 'net.wequick.tools.build:gradle-small:0.1.1'
}
}
...
第二个是
buildscript {
dependencies {
classpath 'net.wequick.tools.build:gradle-small:1.1.0-beta3'
}
}
apply plugin: 'net.wequick.small'
small {
aarVersion = '1.1.0-beta9'
}
启动过程也做了修改,还是能够顺利针对各自的版本进行设置启动。
0.1.1版本只需要在Activity中做设置
@Override
protected void onStart() {
super.onStart();
Small.setBaseUri("http://example.com/");
Small.setUp(this, new net.wequick.small.Bundle.OnLoadListener() {
@Override
public void onStart(int bundleCount, int upgradeBundlesCount, long upgradeBundlesSize) {
}
@Override
public void onProgress(int bundleIndex, String bundleName, long loadedSize, long bundleSize) {
}
@Override
public void onComplete(Boolean success) {
Small.openUri("main", LaunchActivity.this);
}
});
}
1.1.0版本则需要增加一个Application初始化,Small需要你尽早做初始化。
public class SmallApplication extends Application {
public SmallApplication() {
// 这必须在SmallApplication最早的生命周期调用
Small.preSetUp(this);
}
@Override
public void onCreate() {
super.onCreate();
Small.setBaseUri("http://example.com/");// 浏览器跳转url
}
}
//必要点
在启动的第一个Activity,也就是LaunchActvity中的onStart方法中执行setUp方法。这个不能在onCreate中调用。
@Override
protected void onStart() {
super.onStart();
SharedPreferences sp = LaunchActivity.this.getSharedPreferences("profile", 0);
final SharedPreferences.Editor se = sp.edit();
final long tStart = System.nanoTime();
se.putLong("setUpStart", tStart);
Small.setUp(LaunchActivity.this, new net.wequick.small.Small.OnCompleteListener() {
@Override
public void onComplete() {
long tEnd = System.nanoTime();
se.putLong("setUpFinish", tEnd).apply();
long offset = tEnd - tStart;
if (offset < MIN_INTRO_DISPLAY_TIME) {
// 这个延迟仅为了让 "Small Logo" 显示足够的时间, 实际应用中不需要
getWindow().getDecorView().postDelayed(new Runnable() {
@Override
public void run() {
Small.openUri("main", LaunchActivity.this);
finish();
}
}, (MIN_INTRO_DISPLAY_TIME - offset) / 1000000);
} else {
Small.openUri("main", LaunchActivity.this);
finish();
}
}
});
}
运行过程还是唠叨几句,本人是Mac,在Mac下gradlew不具有执行权限,需要在AS终端中执行以下命令:
sudo chmod +x ./gradlew
这样你就能按照官方的方式编译运行了。
然后我自己从零开始构建一个项目,其中遇到的坑也说一下。
- 遇到的第一个坑,我新建的项目SDK默认在版本25,无通过编译,查了一下这貌似是gradle前后版本的兼容问题,也由于25比较新,故先回到老版本。在最顶层的构建文件,写配置供其他组件引用,避免版本不一致通不过编译(编译一次是在太久了,等不下去了)
ext {
compileSdkVersion = 24
buildToolsVersion = "24.0.0"
minSdkVersion = 15
targetSdkVersion = 24
}
在模块构建文件中
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
applicationId "com.example.mysmall.app.main"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
...
}
- 在组件项目中,引入com.android.support:design:24.2.1 ,但是宿主不存在这个包。虽然通过了编译,直接运行还是会报错,说Activity缺失Theme.AppCompat的设置,但其实单独运行组件项目是可以运行。这个问题折腾了我两天。
解决办法:在宿主项目中引入组件项目需要的design包,自然而然地顺利启动了组件的页面。
ButterKnite 在8.0以后还无法支持,暂时将版本定格在7.0.1
由上可知,需要使用apt配置的第三方库都无法支持,因为与small一样利用编译过程,造成冲突。
留个印记,以后或许用得上。
以后或许结合当前在用的APK增量更新,再出一下Small在线更新部分。
[a067ea5c]: http://www.jianshu.com/p/90f1d130f092 "酷狗 Android App 插件化"