点击上方蓝字关注公众号
码个蛋第265次推文
手机淘宝都在用它
作者:在寻找雪见的景天
博客:https://www.jianshu.com/u/3a5162ea1c99
文章目录
-
前言
-
主要功能
-
开始接入
-
重点来了
-
总结步骤
0
前言
Atlas已经出了很久,这几天刚好有个空档期研究了一下,在没啥资料的情况下,加了一堆群,踩了一堆坑,终于成功接入了。本文就是记录接入的过程,并不会讲解太多的原理,想要知道原理的前往:官网(https://link.jianshu.com/?t=http://atlas.taobao.org/)
1主要功能
一、远程Bundle,就是打包的时候不会把这个bundle打包进去,减少apk的安装体积,用户安装apk后,需要加载那个功能的话,就从网上下载这个bundle的so,然后加载打开,当然下载逻辑是app写的。适用模块比较多的app使用,按需加载模块。
二、热更新,就是出补丁包,对一个版本进行代码修改,在不需要用户更新apk的情况下完成更新。
2
开始接入
一、新建一个项目,然后新建几个module,如下图
二、配置1、把gradle改为3.3
2、项目级的build
buildscript { repositories { jcenter() mavenLocal()//本地maven } //引入啊里的依赖,不需要再依赖classpath "com.android.tools.build:gradle"的版本,默认使用的是 2.1 dependencies { classpath "com.taobao.android:atlasplugin:2.3.1.rc9" }}allprojects { repositories { jcenter() mavenLocal()//本地maven }}task clean(type: Delete) { delete rootProject.buildDir}
3、app的build
// 需要放最上面初始化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
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、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 intent; } }); }}
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("更新失败, " + e.getMessage()); } }}
四、安装运行这个版本的apk,界面如下:
1、这个时候点击远程bundle会弹出说没有so文件,因为还没打so包呢2、点击本地bundle,是可以跳转到那个本地bundle页面3、点击更新补丁,会提示更新信息不存在
3
重点来了
下面要打包出远程bundle的so文件,补丁的差异包和更新说明1、打so文件,每个远程都会生成一个so文件的。打开AS的Terminal,输入:gradlew clean assembleDebug publish,然后回车,如下图:
正常的话,会提示这个:
如果提示下面这个错
那就把java进程全部杀掉,然后重试,原因是为啥,我也不知道
成功的话,app的build文件夹里,会生成这个so文件,这个就是远程bundle的so文件,把这个文件放到手机内存卡Android/data/mmc.atlastest/cache 文件夹里面,然后再打开app,点击“远程Bundle”,这个时候就能跳转过去了。
2、更新补丁,打差异包和更新说明接着第一步,然后修改版本号,对本地Bundle进行文字修改,对app主项目也可以修改(修改已有的Activity)
修改后,在Terminal里面输入:gradlew clean assembleDebug -DapVersion=1.0.0 -DversionName=1.0.1回车,成功后会生成补丁差异包和更新说明,如下图:
把红色圈中的两个文件,放到手机内存卡Android/data/mmc.atlastest/cache 文件夹里面,然后点击“更新补丁”,过一会,提示更新成功后,就退出杀死app,再打开就是后面修改的内容了。这样就完成更新过程了,完整源码:AtlasTest(https://link.jianshu.com/?t=https://github.com/LuoGuoXin/AtlasTest)
4
总结步骤
1、配置好,安装1.0.0的app2、用命令“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,重启