AndFix解析——(上)

本文分析了阿里巴巴开源的AndFix Android库的工作原理。重点介绍了PatchManager类的构造函数、init方法及addPatch方法,解释了如何管理和加载补丁文件。

阿里巴巴前一段时间开源了他们用来解决线上紧急bug的一款Android库——AndFix

对Android开发者来说真是一个很好的消息。

基于自己的经验,太长的文字很少有人可以一口气看下来的,所以我打算分成多篇来分析 这是这个库解析的第一篇,

我们先看一下其中的Demo代码,其中调用加载库的代码如下所示:

/**
 * sample application
 * 
 * @author sanping.li@alipay.com
 * 
 */
public class MainApplication extends Application {
	private static final String TAG = "euler";

	private static final String APATCH_PATH = "/out.apatch";
	/**
	 * patch manager
	 */
	private PatchManager mPatchManager;

	@Override
	public void onCreate() {
		super.onCreate();
		// initialize
		mPatchManager = new PatchManager(this);
		mPatchManager.init("1.0");
		Log.d(TAG, "inited.");

		// load patch
		mPatchManager.loadPatch();
		Log.d(TAG, "apatch loaded.");

		// add patch at runtime
		try {
			// .apatch file path
			String patchFileString = Environment.getExternalStorageDirectory()
					.getAbsolutePath() + APATCH_PATH;
			mPatchManager.addPatch(patchFileString);
			Log.d(TAG, "apatch:" + patchFileString + " added.");
		} catch (IOException e) {
			Log.e(TAG, "", e);
		}

	}
}

可以看到代码中首先通过PatchManager的构造函数初始化了PatchManager对象,

PatchManager构造函数

那么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();
}

原来维持了一个Context对象的引用,初始化了AndFixManager对象,mPatchDir对象为存放Patch文件的文件夹,初始化了Patch的集合,还有持有ClassLoader的Map

其中一些内容的声明如下:

private final Context mContext;
private final AndFixManager mAndFixManager;
private final File mPatchDir;
private final SortedSet<Patch> mPatchs;
private final Map<String, ClassLoader> mLoaders;

我们对构造函数的分析在这里就结束了,我们先不深入的跟进Patch和AndFixManager这两个类了。

PatchManager init(String version)

接下来分析PatchManager类中的init(String version)函数, 先来看代码

public void init(String appVersion) {
	//如果mPatchDir不存在,则创建文件夹,如果创建失败,则打印Log
	if(!this.mPatchDir.exists() && !this.mPatchDir.mkdirs()) {
    	Log.e("PatchManager", "patch dir create error.");
    } else if(!this.mPatchDir.isDirectory()) {
	//如果遇到同名的文件,则将该同名文件删除
    	this.mPatchDir.delete();
    } else {
	//在该文件下放入一个名为_andfix_的SharedPreferences文件,
    	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;
}

该方法主要做的事情在注释中即可了解,到这里,第一篇分析就结束了。


原文地址: http://yunair.github.io/blog/2015/09/25/AndFix-%E8%A7%A3%E6%9E%90(%E4%B8%8A).html

【四轴飞行器】非线性三自由度四轴飞行器模拟器研究(Matlab代码实现)内容概要:本文围绕非线性三自由度四轴飞行器模拟器的研究展开,重点介绍基于Matlab代码实现的四轴飞行器动力学建模与仿真方法。研究构建了考虑非线性特性的飞行器数学模型,涵盖姿态动力学与运动学方程,实现了三自由度(滚转、俯仰、偏航)的精确模拟。文中详细阐述了系统建模过程、控制算法设计思路及仿真结果分析,帮助读者深入理解四轴飞行器的飞行动力学特性与控制机制;同时,该模拟器可用于算法验证、控制器设计与教学实验。; 适合人群:具备一定自动控制理论基础和Matlab编程能力的高校学生、科研人员及无人机相关领域的工程技术人员,尤其适合从事飞行器建模、控制算法开发的研究生和初级研究人员。; 使用场景及目标:①用于四轴飞行器非线性动力学特性的学习与仿真验证;②作为控制器(如PID、LQR、MPC等)设计与测试的仿真平台;③支持无人机控制系统教学与科研项目开发,提升对姿态控制与系统仿真的理解。; 阅读建议:建议读者结合Matlab代码逐模块分析,重点关注动力学方程的推导与实现方式,动手运行并调试仿真程序,以加深对飞行器姿态控制过程的理解。同时可扩展为六自由度模型或加入外部干扰以增强仿真真实性。
基于分布式模型预测控制DMPC的多智能体点对点过渡轨迹生成研究(Matlab代码实现)内容概要:本文围绕“基于分布式模型预测控制(DMPC)的多智能体点对点过渡轨迹生成研究”展开,重点介绍如何利用DMPC方法实现多智能体系统在复杂环境下的协同轨迹规划与控制。文中结合Matlab代码实现,详细阐述了DMPC的基本原理、数学建模过程以及在多智能体系统中的具体应用,涵盖点对点转移、避障处理、状态约束与通信拓扑等关键技术环节。研究强调算法的分布式特性,提升系统的可扩展性与鲁棒性,适用于多无人机、无人车编队等场景。同时,文档列举了大量相关科研方向与代码资源,展示了DMPC在路径规划、协同控制、电力系统、信号处理等多领域的广泛应用。; 适合人群:具备一定自动化、控制理论或机器人学基础的研究生、科研人员及从事智能系统开发的工程技术人员;熟悉Matlab/Simulink仿真环境,对多智能体协同控制、优化算法有一定兴趣或研究需求的人员。; 使用场景及目标:①用于多智能体系统的轨迹生成与协同控制研究,如无人机集群、无人驾驶车队等;②作为DMPC算法学习与仿真实践的参考资料,帮助理解分布式优化与模型预测控制的结合机制;③支撑科研论文复现、毕业设计或项目开发中的算法验证与性能对比。; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,重点关注DMPC的优化建模、约束处理与信息交互机制;按文档结构逐步学习,同时参考文中提及的路径规划、协同控制等相关案例,加深对分布式控制系统的整体理解。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值