给现实Android apk打补丁,不用强迫客户升级客户端,悄悄的就把bug修复了,程序猿再也不用被老大骂娘了。 客户端例子实现:https://github.com/fengcunhan/Hotpatch-Sample 服务器简易实现:https://github.com/fengcunhan/Hotpatch-SimpleServer

在手淘工作期间,内部有一套解决方案,给线上apk打补丁,直接修复bug,不用客户端升级,有严重线上bug,找到问题,写个patch,推上线就把问题解决了,用过的都说好。前段时间,他们终于把这套东西的Android端开源了,Dexposed,具体可以看详细的项目介绍。其功能就是可以加载类,替换原先apk里面某个类的方法,或者在方法之前,方法之后做些什么,比如在方法执行之前,修改传入方法的参数了,方法执行以后,修改方法的返回值,或者就是完全替换掉原先的方法。

项目里面有一个sample,介绍了如何加载一个外部apk包,然后替换宿主apk里面类的方法。其实这就已经完成了80%的工作了,我做的工作只是将Patch获取从本地加载改成了去服务器获取,以及添加了Patch apk的校验(md5和签名信息)。

Hotpatch的工作流程是:

1.实现一个从服务器端获取Patch信息的接口(上传本地客户端版本等信息,服务器好根据这些信息来判断是否有对应的Patch包),并将这个信息注入给HotpatchManager。

2.检测客户端是否可以支持。(Android L和Android M)目前都不支持,最低支持2.3

3.如果客户端支持,那就调用第一步注入的Patch包获取类,获取到对应的Patch信息。下载Patch apk文件。

4.校验。获取下载好的Patch apk md5签名信息和服务器给的Patch信息的md5值是否一样,然后还要校验Patch apk和宿主apk签名是否一致。加校验是为了防止Patch apk被篡改,如果load进去了一个第三方的Patch,那就是引狼入室了。一定不能去掉校验,不能去掉,不能去掉,重要的事情说三遍!!!

5.校验成功,就load Patch apk。

下面是贴代码时间:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public class HotpatchManager {
    private static HotpatchManager INSTANCE=new HotpatchManager();
    private HotpatchManager() {
 
    }
 
    public static HotpatchManager getInstance(IPatchInfoRequest request){
        RequestManager.getInstance().setIPatchInfoRequest(request);
        return INSTANCE;
    }
 
    public boolean init(final Context ctx) {
        boolean isSupport = DexposedBridge.canDexposed(ctx);
        if (isSupport) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    check(ctx);
                }
            }).start();
        }
        return isSupport;
    }
 
    private  void check(final Context ctx) {
        RequestManager manager = RequestManager.getInstance();
        manager.setIPatchInfoRequest(RequestManager.getInstance().getIPatchInfoRequest());
        manager.reqeust(new RequestManager.OnRequestCallBackListener() {
            @Override
            public void onRequest(final PatchInfo info) {
                if (null != info) {
                    String apkPath = Utils.getCacheApkFilePath(ctx, info.apkFileUrl);
                    File file = new File(apkPath);
                    if (file.exists()) {
                        loadPath(info, ctx, apkPath);
                    else {
                        DownLoadManager.getInstance().downloadFile(ctx, info.apkFileUrl, new DownLoadManager.OnFileDownload() {
                            @Override
                            public void fileDownload(String apkFilePath) {
                                loadPath(info, ctx, apkFilePath);
                            }
                        });
                    }
                }
            }
        });
    }
 
    private  void loadPath(PatchInfo info, Context ctx, String apkFilePath) {
        if (Utils.isSignEqual(ctx, apkFilePath) && TextUtils.equals(info.apkMd5, Utils.getMd5ByFile(new File(apkFilePath)))) {
            PatchMain.load(ctx, apkFilePath, null);
        }
    }
 
}

已经提供了实现好的客户端和服务器例子。网址分别是:

客户端例子实现:https://github.com/fengcunhan/Hotpatch-Sample

服务器简易实现:https://github.com/fengcunhan/Hotpatch-SimpleServer

运行例子步骤:

1.修改 DefaultPatch类中的info.patchApkUrl  的url中的IP替换成你的服务器的IP,将代码部署到tomcat中。

2.导入Hotpatch-Sample中的工程到Android Studio中。

3.打开网址 http://服务器IP:服务器端口/PathServer,将patchsample下build/outputs/apk/app-debug.apk上传到服务器上面,一定不要改名字。

4.修改DefaultPatchInfoRequest 中的hostUrl的IP和端口为你的服务器端IP和端口。

5.运行dexposedexamples项目,点击 Check Hotpatch,如果出现 “The dialog is shown from patch apk”,恭喜你,成功运行了Demo。

Demo中的Patch只是很简单的一个例子,后续会碰到混淆的类怎么怎么写Patch之类的问题,这些都将在以后一一叙述。请大家关注这个Hotpatch系列。

Demo中服务器实现很渣渣。请服务器端大神不要喷,可以fork,不要fuck。

Android Hotpatch系列之-项目介绍的更多相关文章

  1. Android Hotpatch系列之-给release包打Patch

    在默认debug包里面,是不对class做混淆的,所以Patch编写相对简单,但是应用在发布的时候都是release包,会对代码做混淆,此时class name ,field name,method ...

  2. 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

    [原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

  3. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  4. 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新

    本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...

  5. Android项目实战之高仿网易云音乐项目介绍

    这一节我们来讲解这个项目所用到的一些技术,以及一些实现的效果图,让大家对该项目有一个整体的认识,推荐大家收藏该文章,因为我们发布文章后会在该文章里面加入链接,这样大家找着就很方便. 目录 第1章 前期 ...

  6. 一、VUE项目BaseCms系列文章:项目介绍与环境配置

    一.项目效果图预览: 二.项目介绍 基于 elementui 写一个自己的管理后台.这个系列文章的目的就是记录自己搭建整个管理后台的过程,希望能帮助到那些入门 vue + elementui 开发的小 ...

  7. [转]Android Studio系列教程六--Gradle多渠道打包

    转自:http://www.stormzhang.com/devtools/2015/01/15/android-studio-tutorial6/ Android Studio系列教程六--Grad ...

  8. Android Studio系列教程六--Gradle多渠道打包

    Android Studio系列教程六--Gradle多渠道打包 2015 年 01 月 15 日 DevTools 本文为个人原创,欢迎转载,但请务必在明显位置注明出处!http://stormzh ...

  9. Android Studio系列教程五--Gradle命令详解与导入第三方包

    Android Studio系列教程五--Gradle命令详解与导入第三方包 2015 年 01 月 05 日 DevTools 本文为个人原创,欢迎转载,但请务必在明显位置注明出处!http://s ...

随机推荐

  1. 配置spring事务管理的几种方式(声明式事务)

    Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource.TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分. DataSo ...

  2. PHP中的变量详解

    php变量通过名只能我们就知道首先变量,是在程序执行期间,可以变化的量. 1.那变量是干嘛的呢,用变量就可以来保存我们值,这就是变量,那么我们接着来看,知道了变量是什么,以及它能干什么,我们再来看一下 ...

  3. js时间格式转换

    在javascript中直接输出Date得到的结果是这样的: function date(){ var date = new Date(); alert(date); } 结果是:Mon Jun 15 ...

  4. DAS、SAN、NAS的区别

    在服务企业的过程中,经常会接触到存储,但是又容易和市面上的一些什么NAS等混淆. DAS 与主机直连的存储设备 NAS 存储设备自带文件系统 SAN 存储设备的互联依赖网络,比如IP-SAN, FC- ...

  5. C++指针之防不胜防

    我们在使用指针时,经常会出现下面几种错误: 1) 内存分配未成功,却使用了它. 编程新手常犯这种错误,因为他们没有意识到内存分配会不成功.常用解决办法是,在使用内存之前检查指针是否为NULL.如果指针 ...

  6. 远程实时调试手机上的Web页面

    1. 安装    需要Node.js平台, 先安装好后, 打开Node.js command prompt, 通过NPM来安装 weinre npm -g install weinre 2. 启动   ...

  7. jQuery水平下拉菜单实现

    <!DOCTYPE html> <html>    <head>       <title>jQuery水平下拉菜单实现</title>   ...

  8. ListView在列表的头部和底部添加布局——addHeaderView,addFooterView

    addHeaderView()方法:主要是向listView的头部添加布局addFooterView()方法:主要是向listView的底部添加布局 以addHeaderView为例: View he ...

  9. 编译安装的 mysql apache 用 service mysqld start 来启动

    先我们把mysql增加到linux的系统服务中去 mysql:  代码如下 复制代码 cd /usr/local/mysql/share/mysql cp mysql.server /etc/init ...

  10. iOS开发UI篇—Quartz2D使用(图形上下文栈)

    iOS开发UI篇—Quartz2D使用(图形上下文栈) 一.qurza2d是怎么将绘图信息和绘图的属性绘制到图形上下文中去的? 说明: 新建一个项目,自定义一个view类和storyboard关联后, ...