概述
Atlas 是伴随着手机淘宝不断发展而衍生出来的一个运行于 Android 系统上的插件化框架,也可以叫动态组件化框架,主要提供了解耦化、组件化、动态性的支持。是目前比较成熟的方案,功能强大,但相对的,使用和集成的难度也比较大。
Atlas是Hadoop的数据治理和元数据框架。 Atlas是一组可扩展和可扩展的核心基础治理服务,使企业能够有效,高效地满足Hadoop中的合规性要求,并允许与整个企业数据生态系统集成。 Apache Atlas为组织提供了开放的元数据管理和治理功能,以建立其数据资产的目录,对这些资产进行分类和治理,并为数据科学家,分析师和数据治理团队提供围绕这些数据资产的协作功能。
Atlas 的优点:
- 稳定,成熟,功能强悍
- 维护团队比较负责,技术实力值得信赖
- 能承担大体量应用的插件化改造,例如手机淘宝这样的巨型应用
- 能够实现单 bundle 的快速调试(速度类似于 freeline 增量编译)
- 具有远程插件和动态部署功能,可以实现热修复和线上版本发布功能
Atlas 的缺点:
- 集成较为复杂。
- 文档很是简略。
- 本管理较为复杂。
- 官方的动态部署方法,需要根据版本来下方补丁包。
- 插件必须要以 library 的形式,如果需要单独打包,需要自己配置 gradle 文件,并且每个 bundle 都得进行 atlas 配置,没有和 atlas 完全分离。
- 插件跳转必须通过 activity ,如果是旧项目迁移,可能有一定的改造成本。
图示
- Atlas支持各种Hadoop和非Hadoop元数据类型
- 提供了丰富的REST API进行集成
- 对数据血缘的追溯达到了字段级别,这种技术还没有其实类似框架可以实现
- 对权限也有很好的控制
架构原理
Atlas包括以下组件:
- 采用Hbase存储元数据
- 采用Solr实现索引
- Ingest/Export 采集导出组件 Type System类型系统 Graph Engine图形引擎 共同构成Atlas的核心机制
- 所有功能通过API向用户提供,也可以通过Kafka消息系统进行集成 Atlas支持各种源获取元数据:Hive,Sqoop,Storm。
- 还有优秀的UI支持
效果图
Atlas项目实践
前面我们介绍了Atlas的一些原理性的东西,总的来说,Atlas就是利用远程Bundle的下发方式,为了减少apk的安装体积,Atlas项目使用bundle的加载方式。当用户安装没有Bundle的apk文件时,就从网上下载这个bundle的so,然后加载打开,下载逻辑使用app原生代码编写,加载用按需加载的策略。
Atlas接入
首先新建一个项目,然后新建几个module,如下图。
修改配置
1,把gradle改为3.3
2,然后我们需要为Atlas添加一些配置,引用Atlas插件及依赖仓库,修改工程gradle文件。
//不需要再依赖classpath "com.android.tools.build:gradle"
classpath "com.taobao.android:atlasplugin:2.3.3.beta2"
3,修改app的build.gradle脚本,需要注意包名的对应关系。
// 需要放最上面初始化
group = "mmc.atlastest"
version = getEnvValue("versionName", "1.0.0");
def apVersion = getEnvValue("apVersion", "");
apply plugin: 'com.android.application'
apply plugin: 'com.taobao.atlas'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "mmc.atlastest"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName version
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.3.1'
testCompile 'junit:junit:4.12'
//atlas的依赖
compile('com.taobao.android:atlas_core:5.0.7@aar') {
transitive = true
}
compile 'com.taobao.android:atlasupdate:1.1.4.7@aar'
compile 'com.alibaba:fastjson:1.1.45.android@jar'
//项目依赖
compile project(':librarybundle')
compile project(':localbundle')
compile project(':remotebundle')
}
//加入以下配置
atlas {
atlasEnabled true
tBuildConfig {
// autoStartBundles = ['com.android.homebundle'] //自启动bundle配置
outOfApkBundles = ['remotebundle'] //远程module,列表来的,可填多个
preLaunch = 'mmc.atlastest.AtlasLaunch' //AppApplication启动之前调用,这个类下面放出代码
}
patchConfigs {
debug {
createTPatch true
}
}
buildTypes {
debug {
if (apVersion) {
// 打差异补丁 gradlew assembleDebug -DapVersion=1.1.0 -DversionName=1.1.1
// 对应着本地maven仓库地址 .m2/repository/mmc/atlastest/AP-debug/1.1.4/AP-debug-1.1.4.ap
baseApDependency "mmc.atlastest:AP-debug:${apVersion}@ap"
patchConfig patchConfigs.debug
}
}
}
}
String getEnvValue(key, defValue) {
def val = System.getProperty(key);
if (null != val) {
return val;
}
val = System.getenv(key);
if (null != val) {
return val;
}
return defValue;
}
apply plugin: 'maven'
apply plugin: 'maven-publish'
publishing {
// 指定仓库位置
repositories {
mavenLocal()
}
publications {
// 默认本地仓库地址 用户目录/.m2/repository/
maven(MavenPublication) {
//读取ap目录上传maven
artifact "${project.buildDir}/outputs/apk/${project.name}-debug.ap"
//生成本地maven目录
groupId group
artifactId "AP-debug"
4,修改远程bundle和本地bundle的build.gradle脚本
apply plugin: 'com.android.library'
apply plugin: 'com.taobao.atlas'
atlas {
bundleConfig{
awbBundle true
}
buildTypes {
debug {
baseApFile project.rootProject.file('app/build/outputs/apk/app-debug.ap')
}
}
}
//只添加上面的配置就行了,下面的是默认生成的
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.3.1'
testCompile 'junit:junit:4.12'
//依赖lib中间bundle
compile project(':librarybundle')
}
5,在宿主app的application中添加如下代码。
public class DemoApplication extends Application
@Override
public void onCreate() {
super.onCreate();
Atlas.getInstance().setClassNotFoundInterceptorCallback(new ClassNotFoundInterceptorCallback() {
@Override
public Intent returnIntent(Intent intent) {
final String className = intent.getComponent().getClassName();
final String bundleName = AtlasBundleInfoManager.instance().getBundleForComponet(className);
if (!TextUtils.isEmpty(bundleName) && !AtlasBundleInfoManager.instance().isInternalBundle(bundleName)) {
//远程bundle
Activity activity = ActivityTaskMgr.getInstance().peekTopActivity();
File remoteBundleFile = new File(activity.getExternalCacheDir(),"lib" + bundleName.replace(".","_") + ".so");
String path = "";
if (remoteBundleFile.exists()){
path = remoteBundleFile.getAbsolutePath();
}else {
Toast.makeText(activity, " 远程bundle不存在,请确定 : " + remoteBundleFile.getAbsolutePath() , Toast.LENGTH_LONG).show();
return intent;
}
PackageInfo info = activity.getPackageManager().getPackageArchiveInfo(path, 0);
try {
Atlas.getInstance().installBundle(info.packageName, new File(path));
} catch (BundleException e) {
Toast.makeText(activity, " 远程bundle 安装失败," + e.getMessage() , Toast.LENGTH_LONG).show();
e.printStackTrace();
}
activity.startActivities(new Intent[]{intent});
}
return
6、在app新建一个类AtlasLaunch,继承AtlasPreLauncher。
public class AtlasLaunch implements AtlasPreLauncher
@Override
public void initBeforeAtlas(Context context) {
}
}
项目结构 然后写app的基本功能,示例如下图。
下面是宿主中具体的跳转逻辑实现。
public class MainActivity extends BaseActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//打开远程bundle
public void remote(View view){
Intent intent = new Intent();
intent.setClassName(view.getContext(), "mmc.remotebundle.RemoteActivity");
startActivity(intent);
}
//打开本地bundle
public void local(View view){
Intent intent = new Intent();
intent.setClassName(view.getContext(), "mmc.localbundle.LocalActivity");
startActivity(intent);
}
//更新补丁
public void update(View view){
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
update();
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
Toast.makeText(MainActivity.this, "更新完成,请重启", Toast.LENGTH_LONG).show();
}
}.execute();
}
private void update(){
File updateInfo = new File(getExternalCacheDir(), "update.json");
if (!updateInfo.exists()) {
showToast("更新信息不存在,请先 执行 buildTpatch.sh");
return;
}
String jsonStr = new String(FileUtils.readFile(updateInfo));
UpdateInfo info = JSON.parseObject(jsonStr, UpdateInfo.class);
File patchFile = new File(getExternalCacheDir(), "patch-" + info.updateVersion + "@" + info.baseVersion + ".tpatch");
try {
AtlasUpdater.update(info, patchFile);
} catch (Throwable e) {
e.printStackTrace();
showToast("更新失败, "
安装运行项目,就可以看到如下图所示的效果。
此时还有以下工具需要完成:
1,这个时候点击远程bundle会弹出说没有so文件,因为还没打so包呢
2、点击本地bundle,是可以跳转到那个本地bundle页面
3、点击更新补丁,会提示更新信息不存在
打远程bundle的so文件 下面要打包出远程bundle的so文件,补丁的差异包和更新说明。
1,打so文件,每个远程都会生成一个so文件的。打开AS的Terminal,输入:gradlew clean assembleDebug publish,然后回车,如下图:
正常的话,会提示下面的正确信息。
成功的话,app的build文件夹里,会生成这个so文件,这个就是远程bundle的so文件,把这个文件放到手机内存卡Android/data/mmc.atlastest/cache 文件夹里面,然后再打开app,点击“远程Bundle”,这个时候就能跳转过去了。
更新补丁,打差异包和更新说明 接着第一步,然后修改版本号,对本地Bundle进行文字修改,对app主项目也可以修改。
修改后,在Terminal里面输入:gradlew clean assembleDebug -DapVersinotallow=1.0.0 -Dversinotallow=1.0.1
回车,成功后会生成补丁差异包和更新说明,如下图:
把红色圈中的两个文件,放到手机内存卡Android/data/mmc.atlastest/cache 文件夹里面,然后点击“更新补丁”,过一会,提示更新成功后,就退出杀死app,再打开就是后面修改的内容了。
以上就是Android插件化中的Atlas原理以及实战浅析,如果想更深入学习Android插件化或者进阶核心技术,可以参考《Android核心技术手册》文档,里面技术归纳了几十个知识点。更加前面方便学习,点击查看获取方法。
Atlas使用步骤总结
1、配置好,安装1.0.0的app
2、用命令“gradlew clean assembleDebug publish”打AP,得到远程Bundle的so文件
3、修改版本号,修改版本内容
4、用命令“gradlew clean assembleDebug -DapVersion=1.0.0 -DversionName=1.0.1”打差异包补丁和更新说明
5、把上面得到的三个文件放到app的cache目录里面
6、运行更新方法,杀死app,重启
网友评论