AndFix介绍:
AndFix,全称是Android hot-fix。是阿里开源的一个Android热补丁框架,允许APP在不重新发布版本的情况下修复线上的bug。支持Android 2.3 到 6.0。
依赖:
compile 'com.alipay.euler:andfix:0.3.1@aar'
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private Button repairbug; private Button createbug; private String path=""; private String pathName="out.apatch"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); createbug = findViewById(R.id.create_bug); repairbug = findViewById(R.id.repair_bug); createbug.setOnClickListener(this); repairbug.setOnClickListener(this); if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ String absolutePath = Environment.getExternalStorageDirectory().getAbsolutePath()+"/Movies"; path=absolutePath.concat(File.separator).concat(pathName); Log.d("zzz","补丁路径:"+path); File file = new File(path); if(!file.exists()){ try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } } } @Override public void onClick(View v) { switch (v.getId()){ case R.id.create_bug: createBug(); break; case R.id.repair_bug: repairaBug(); break; } } //修复Bug private void repairaBug() { AndFixManager.getInstance().initPath(path); Toast.makeText(this,"已修复", Toast.LENGTH_SHORT).show(); } //创建Bug public void createBug(){ int a=5; a=a/0; Toast.makeText(this,a+"",Toast.LENGTH_SHORT).show(); } }AndFixManager.java
public class AndFixManager { private static volatile AndFixManager instance; private PatchManager patchManager; private AndFixManager(){} public static AndFixManager getInstance(){ if(instance==null){ synchronized (AndFixManager.class){ if(null==instance){ instance=new AndFixManager(); } } } return instance; } public void initAndFix(Context context,String appversion){ patchManager = new PatchManager(context); patchManager.init(appversion);//current version patchManager.loadPatch(); } public void initPath(String path){ try { patchManager.addPatch(path); } catch (IOException e) { e.printStackTrace(); } } }MyApplication.java
public class MyApplication extends Application{ @Override public void onCreate() { super.onCreate(); initAndfix(this); } public void initAndfix(Context context){ try { String appversion= getPackageManager().getPackageInfo(getPackageName(),0).versionName; AndFixManager.getInstance().initAndFix(context,appversion); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } } }
大致原理
apkpatch将两个apk做一次对比,然后找出不同的部分。可以看到生成的apatch了文件,后缀改成zip再解压开,里面有一个dex文件。通过jadx查看一下源码,里面就是被修复的代码所在的类文件,这些更改过的类都加上了一个_CF的后缀,并且变动的方法都被加上了一个叫@MethodReplace的annotation,通过clazz和method指定了需要替换的方法。然后客户端sdk得到补丁文件后就会根据annotation来寻找需要替换的方法。最后由JNI层完成方法的替换。
多次打补丁
如果本地保存了多个补丁,那么AndFix会按照补丁生成的时间顺序加载补丁。具体是根据.apatch文件中的PATCH.MF的字段Created-Time。
安全性
readme提示开发者需要验证下载过来的apatch文件的签名是否就是在使用apkpatch工具时使用的签名,如果不验证那么任何人都可以制作自己的apatch文件来对你的APP进行修改。但是我看到AndFix已经做了验证,如果补丁文件的证书和当前apk的证书不是同一个的话,就不能加载补丁。官网还有一条,提示需要验证optimize file的指纹,应该是为了防止有人替换掉本地保存的补丁文件,所以要验证MD5码,然而SecurityChecker类里面也已经做了这个工作。。但是这个MD5码是保存在sharedpreference里面,如果手机已经root那么还是可以被访问的。