@linux1s1s
2017-01-22T08:54:41.000000Z
字数 3837
阅读 2331
AndroidExtend 2016-03
上一篇博文介绍了patch补丁是如何制作的,这里先从Demo入手,深入源码看看补丁到底是如何生效的。
先来看看Demo,在Application的onCreate()生命周期中加入以下代码。
private static final String APATCH_PATH = "/out.apatch";@Overridepublic void onCreate(){super.onCreate();/*patch manager*/PatchManager patchManager = new PatchManager(this);patchManager.init("1.0");// load patchpatchManager.loadPatch();// add patch at runtimetry {// apatch file pathString patchFileString = Environment.getExternalStorageDirectory().getAbsolutePath() + APATCH_PATH;patchManager.addPatch(patchFileString);} catch (IOException e) {e.printStackTrace();}}
L10 PatchManager管理类构造器
public PatchManager(Context context) {this.mContext = context;this.mAndFixManager = new AndFixManager(this.mContext);this.mPatchDir = new File(this.mContext.getFilesDir(), "apatch");this.mPatchs = new ConcurrentSkipListSet();this.mLoaders = new ConcurrentHashMap();}
PatchManager管理类 组合了AndFixManager管理类,apatch补丁存放目录和两个容器。回到Application中的L11 初始化操作
public void init(String appVersion) {if(!this.mPatchDir.exists() && !this.mPatchDir.mkdirs()) {Log.e("PatchManager", "patch dir create error.");} else if(!this.mPatchDir.isDirectory()) {this.mPatchDir.delete();} else {SharedPreferences sp = this.mContext.getSharedPreferences("_andfix_", 0);String ver = sp.getString("version", (String)null);if(ver != null && ver.equalsIgnoreCase(appVersion)) {this.initPatchs();} else {this.cleanPatch();sp.edit().putString("version", appVersion).commit();}}}
接下来我们分析上面代码中的如下代码
//如果从_andfix_这个文件获取的ver不是null,而且这个ver和外部初始化时传进来的版本号一致if(ver != null && ver.equalsIgnoreCase(appVersion)) {this.initPatchs();} else {this.cleanPatch();sp.edit().putString("version", appVersion).commit();}
先看else内的内容,else里执行力cleanPatch()和把外部初始化的时候传进来的版本号放入SharedPreferences里。 cleanPatch()做了什么操作呢,我们跟进去看一看
private void cleanPatch() {//获取mPatchDir目录下所有文件File[] files = this.mPatchDir.listFiles();File[] arr$ = files;int len$ = files.length;for(int i$ = 0; i$ < len$; ++i$) {File file = arr$[i$];//将此文件从OptFile文件夹删除this.mAndFixManager.removeOptFile(file);//这个方法的作用就是如果file是文件,则删除它,如果file是文件夹,则将它和它里面的文件都删除if(!FileUtil.deleteFile(file)) {Log.e("PatchManager", file.getName() + " delete error.");}}}
如源码中的注释,就是删除了之前在那两个文件夹下的所有的补丁文件。
现在来分析一下this.initPatchs()做了什么事
private void initPatchs() {File[] files = this.mPatchDir.listFiles();File[] arr$ = files;int len$ = files.length;for(int i$ = 0; i$ < len$; ++i$) {File file = arr$[i$];this.addPatch(file);}}
代码很简单,就是把mPatchDir文件夹下的文件作为参数传给了addPatch(File)方法 那this.addPatch(file)做了什么呢
//把扩展名为.apatch的文件传给Patch做参数,初始化对应的Patch,//并把刚初始化的Patch加入到我们之前看到的Patch集合mPatchs中private Patch addPatch(File file) {Patch patch = null;//扩展名是否为".apatch"if(file.getName().endsWith(".apatch")) {try {patch = new Patch(file);this.mPatchs.add(patch);} catch (IOException var4) {Log.e("PatchManager", "addPatch", var4);}}return patch;}
上面的代码很好理解,此时,我们已经完整的走下来了init(String version)这个方法。 再次出现了Patch这个类,但是我们依然要把它放在一边,因为由于篇幅限制,第一篇不会分析这个类。
接下来,我们继续跟着demo走,会执行两个方法,一个mPatchManager.loadPatch(),一个mPatchManager.addPatch(patchFileString), loadPatch()方法是这个库执行替换的核心方法,我会在以后单独写一篇文章来分析,所以,在这篇文章的最后,我们跟进addPatch(String)这个方法一看究竟
public void addPatch(String path) throws IOException {File src = new File(path);File dest = new File(this.mPatchDir, src.getName());if(dest.exists()) {//在mPatchDir文件夹下存在该文件,则AndFixManager移除该文件this.mAndFixManager.removeOptFile(dest);}//将文件从src复制到dest,只不过阿里用了NIO来复制文件FileUtil.copyFile(src, dest);//调用了另外一个addPatch方法,以文件作为参数Patch patch = this.addPatch(dest);if(patch != null) {//同样调用了loadPatch(Patch)方法this.loadPatch(patch);}}
简单来说,上面的方法就是将补丁文件复制到/data/data/{包名}/apatch 目录内,如果在OptFile文件夹中存在,则删除。 然后调用另外一个addPatch(File)方法,然后loadPatch() 下面,我们来看一下重载的addPatch(File)方法
private Patch addPatch(File file) {Patch patch = null;if(file.getName().endsWith(".apatch")) {try {patch = new Patch(file);//把从file文件生成的patch加入到mPatchs这个Set中this.mPatchs.add(patch);} catch (IOException var4) {Log.e("PatchManager", "addPatch", var4);}}return patch;}
到这里,我们分析完成了Demo中的AndFix方法,留下来三个坑,分别是一个方法mPatchManager.loadPatch()方法和两个类AndFixManager和Patch类,等到后面再补上。
附注: 此文章转载并微修改自AndFix解析,特此说明。
