首先有这方面需要的请到https://github.com/xiangzhihong/andfixDemo/tree/master下载例子

对于网上提供的热补丁修复就不多说了,主要有这3种方式可以实现(至于其他的方式,暂不清楚)

1.dexposed     github https://github.com/alibaba/dexposed

2.andfix   github https://github.com/alibaba/AndFix

3.bsdiff  http://blog.csdn.net/lazyer_dog/article/details/47173013

dexposed和andfix是alibaba的开源项目,都是apk增量更新的实现框架,目前dexposed的兼容性较差,只有2.3,4.0~4.4兼容,其他Android版本不兼容或未测试,详细可以去dexposed的github项目主页查看,而andfix则兼容2.3~6.0,所以就拿这个项目来实现增量更新吧。至于bsdiff,只是阅览了一下,还没研究过。

首先 git clone github https://github.com/alibaba/AndFix,将andfix项目下载下来,Android studio可以在build.gradle里导入andfix,

compile 'com.alipay.euler:andfix:0.3.1'

但是我是使用module的方式添加andfix,这样可以直接查看编辑源码,而且直接gradle导入的话还有个问题,后面再说。

我看了下官网的demo主要是在android装载到内存的时候去加载我们新的dex的包,然后加载到内存,要研究原理的请到这个地址去查看:

http://blog.csdn.net/xiangzhihong8/article/details/50949691

下面主要说实现:

andfix里有些文件夹不用导入的,例如tools,doc等,记得新建jniLibs文件夹,libs里的so文件移到jniLibs里。

接下来我们参照官网的demo

public class MainApplication extends Application {
    private static final String TAG = "euler";

    private static final String APATCH_PATH = "/out.apatch";

    private static final String DIR = "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.");

            //这里我加了个方法,复制加载补丁成功后,删除sdcard的补丁,避免每次进入程序都重新加载一次
            File f = new File(this.getFilesDir(), DIR + APATCH_PATH);
            if (f.exists()) {
                boolean result = new File(patchFileString).delete();
                if (!result)
                    Log.e(TAG, patchFileString + " delete fail");
            }
        } catch (IOException e) {
            Log.e(TAG, "", e);
        }

    }

刚刚说的直接在gradle里导入andfix会有个问题,是在原来的项目中,加载一次补丁后,out.apatch文件会copy到getFilesDir目录下的/apatch文件夹中,在下次补丁更新时,会检测补丁是否已经添加在apatch文件夹下,已存在就不会复制加载sdcard的out.apatch。

原来的addpath方法

public void addPatch(String path) throws IOException {
    File src = new File(path);
    File dest = new File(mPatchDir, src.getName());
    if(!src.exists()){
        throw new FileNotFoundException(path);
    }
    if (dest.exists()) {
        Log.d(TAG, "patch [" + path + "] has be loaded.");
        return;
    }
    FileUtil.copyFile(src, dest);// copy to patch's directory
    Patch patch = addPatch(dest);
    if (patch != null) {
        loadPatch(patch);
    }
}

修改后,判断apatch下的out.apatch存在即删除掉,重新复制加载sdcard下的out.apatch

public void addPatch(String path) throws IOException {
    File src = new File(path);
    File dest = new File(mPatchDir, src.getName());
    if (!src.exists()) {
        throw new FileNotFoundException(path);
    }
    if (dest.exists()) {
        Log.d(TAG, "patch [" + src.getName() + "] has be loaded.");
        boolean deleteResult = dest.delete();
        if (deleteResult)
            Log.e(TAG, "patch [" + dest.getPath() + "] has be delete.");
        else {
            Log.e(TAG, "patch [" + dest.getPath() + "] delete error");
            return;
        }
    }
    FileUtil.copyFile(src, dest);// copy to patch's directory
    Patch patch = addPatch(dest);
    if (patch != null) {
        loadPatch(patch);
    }
}

还有源码混淆

-optimizationpasses 5                                                           # 指定代码的压缩级别
-dontusemixedcaseclassnames                                                     # 是否使用大小写混合
-dontskipnonpubliclibraryclasses                                                # 是否混淆第三方jar
-dontpreverify                                                                  # 混淆时是否做预校验
-verbose                                                                        # 混淆时是否记录日志
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*        # 混淆时所采用的算法

#重要,別忘了這些,不混淆andfix包,不混淆native方法
-dontwarn android.annotation
-dontwarn com.alipay.euler.**
-keep class com.alipay.euler.** {*;}
-keep class * extends java.lang.annotation.Annotation
-keepclasseswithmembernames class * {
    native <methods>;
}

下面我们打包:

cmd输入命令,具体参数看usage

apkpatch.bat -f new.apk -t old.apk -o output1 -k suning.keystore -p Suning1234 -a suning -e Suning1234 【完整命令】

上面这个命令有点问题,用下面的:

apkpatch -f new.apk -t old.apk -o output -k xzh.jks -p 19881205 -a keyalias -e 19881205

解释下这个意思,apkpatch -f <new apk> -t <old.apk> -o<输出位置> -k <keystore> -p<password> -a <key alias> -e <password>

这里的keystore就是你签名包

如无错误,编译后会生成一个apatch文件,改名成out.apatch

里面的smali列出了不同的文件,diff.dex就是android 虚拟机加载运行的不同的文件。

安装打开1.apk

关闭app,将out.apatch放sdcard根目录后,重新打开app,toast方法改变了

2)  几个开源热修复或插件化解决方案(排名不分先后)

https://github.com/lzyzsd/AndroidHotFixExamples

https://github.com/simpleton/dalvik_patch

https://github.com/dodola/HotFix

https://github.com/jasonross/Nuwa

https://github.com/alibaba/AndFix

https://github.com/rovo89/Xposed

https://github.com/alibaba/dexposed

https://github.com/bunnyblue/DroidFix

https://github.com/CtripMobile/DynamicAPK

3)  技术原理博客(排名不分先后)

http://bugly.qq.com/blog/?p=781(QQ空间的解决方案)

https://m.oschina.net/blog/308583(Android Dex分包方案)

http://lirenlong.github.io/hotfix/(浅析xposed、dexposed和AndFix的原理)

http://blog.csdn.net/lmj623565791/article/details/49883661(鸿洋)

http://blog.csdn.net/vipzjyno1/article/details/21039349/(android反编译)

android 热修补之andfix实践的更多相关文章

  1. 爱奇艺技术分享:爱奇艺Android客户端启动速度优化实践总结

    本文由爱奇艺技术团队原创分享,原题<爱奇艺Android客户端启动优化与分析>. 1.引言 互联网领域里有个八秒定律,如果网页打开时间超过8秒,便会有超过70%的用户放弃等待,对Andro ...

  2. Android App 性能优化实践

    本文记录了Android App优化需要用到的工具和以及在实践中的Tips.也算对我这半年来部分工作的总结. 工具 Hierarchy Viewer 是 Android SDK 自带的 Layout ...

  3. (转)Android开发:性能最佳实践-管理应用内存

    翻自:http://developer.android.com/training/articles/memory.html 在任何软件开发环境中,RAM都是宝贵的资源,但在移动操作系统中更加珍贵.尽管 ...

  4. Robotium之Android控件定位实践和建议(Appium/UIAutomator姊妹篇)

    本人之前以前撰文描写叙述Appium和UIAutomator框架是怎样定位Android界面上的控件的. UIAutomator定位Android控件的方法实践和建议 Appium基于安卓的各种Fin ...

  5. Android 模块化探索与实践

    首发于<程序员>杂志五月刊 一.前言 万维网发明人 Tim Berners-Lee 谈到设计原理时说过:"简单性和模块化是软件工程的基石:分布式和容错性是互联网的生命." ...

  6. Android Studio Git 分支实践

    新公司有些项目是用的 Git,以前公司都是 svn,为了练手 Git,我个人 APP 用到了,但是仅简单的 git pull/push 的使用,并未用到 Git 精髓,只有当项目中用到,才会紧迫去全面 ...

  7. Robotium之Android控件定位实践和建议

    本人之前曾经撰文描述Appium和UIAutomator框架是如何定位Android界面上的控件的. UIAutomator定位Android控件的方法实践和建议Appium基于安卓的各种FindEl ...

  8. Android MVP+Retrofit+RxJava实践小结

    关于MVP.Retrofit.RxJava,之前已经分别做了分享,如果您还没有阅读过,可以猛戳: 1.Android MVP 实例 2.Android Retrofit 2.0使用 3.RxJava ...

  9. Android热修复AndFix

    热修复主要用来修复代码.修复bug.添加独立的功能,他的原理主要是操作PathClassLoader.DexClassLoader. PathClassLoader是类加载器,DexClassLoad ...

随机推荐

  1. Java进阶(四十四)线程与进程的特征及区别

    线程与进程的特征及区别 定义及特征 进程   指在系统中能独立运行并作为资源分配的基本单位,它是由一组机器指令.数据和堆栈等组成的,是一个能独立运行的活动实体. 进程的特征: 1.动态性:进程的实质是 ...

  2. Linux Java开发坏境搭建,Ubuntu-jdk+tomcat+eclipse+svn 包安装详细操作

    更新时间2015-03-15 更新2015-04-12 svn安装更新 第一步 安装jdk (在linux上使用yum安装JDK  http://blog.chinaunix.net/uid-1546 ...

  3. C语言一个双向链表的实现

    首先编写头文件,头文件里做相关的定义和声明,DList.h内容如下: #ifndef DList_H #define DList_H typedef int Item; typedef struct ...

  4. android横竖屏切换activity生命周期变化

    1.新建一个Activity,并把各个生命周期打印出来 2.运行Activity,得到如下信息 onCreate--> onStart--> onResume--> 3.按crtl+ ...

  5. 1070. Mooncake (25)

    题目如下: Mooncake is a Chinese bakery product traditionally eaten during the Mid-Autumn Festival. Many ...

  6. ADFS部署过程中设置network service对证书的读取权限

    今儿在部署客户正式环境的ADFS时候遇到一问题,在配置完基于声明的身份验证后通过url访问居然报错了,这干过N回的事怎么会出错了呢,百思不得其解 网页报错如下 系统日志报错如下, 回想过程中的每一步, ...

  7. 设计比较好,有助于学习的Github上的iOS App源码 (中文)

    Github版 中文 : TeamTalk 蘑菇街. 开源IM. 电商强烈推荐. MyOne-iOS 用OC写的<一个> iOS 客户端 zhihuDaily 高仿知乎日报 Coding ...

  8. Swing中经常会遇到的若干问题——JTable(持续更新)

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/40955213 (1)让组件在屏幕中央显示 public s ...

  9. 使用github管理你的代码

    关于为什么使用github,网上已经有很多讨论了.当然选择还有google code, Bitbucket,sourceforge.github有如下优势: 1. github更有利于开源项目的发展 ...

  10. Github搭建属于自己的开源项目-androd学习之旅(72)

    Github是一个基于的git的版本控制工具,分为私人代码管理和开源代码管理,下面我们简单的介绍一下 首先登陆官网https://github.com 完成注册,随后首页会有四个模块,第一个是安装的指 ...