Android 热更新——非侵入AOP框架

Android 客户端应用上线以后,一旦出现Bug,一般的解决思路是发修复包升级应用,这种方式不仅耗时,更重要的是用户需要频繁的升级版本,体验不好,所以优化的思路是在不发版本的情况下热更新,以期提高用户体验。

近期GitHub新出一种非侵入运行期AOP框架Dexposed, 下面简单了解一下这个框架,GitHub地址

简要说明:

该框架基于AOP思想,支持经典的AOP使用场景,可应用于日志记录,性能统计,安全控制,事务处理,异常处理等方面。

针对Android平台,Dexposed支持函数级别的在线热更新,例如对已经发布在应用市场上的宿主APK,当我们从crash统计平台上发现某个函数调用有bug,导致经常性crash,这时,可以在本地开发一个补丁APK,并发布到服务器中,宿主APK下载这个补丁APK并集成后,就可以很容易修复这个crash。

Dexposed是基于久负盛名的开源Xposed框架实现的一个Android平台上功能强大的无侵入式运行时AOP框架。Dexposed的AOP实现是完全非侵入式的,没有使用任何注解处理器,编织器或者字节码重写器。

Patch原理

首先从GitHub上拉下来代码有几个坑需要注意:

  • 如果想直接拿过来用,你可能会失望而归,因为patchsample这个android程序就没有入口Activity,所以需要自行新建。
  • 注意Lib包如何添加,不能直接添加在libs这个工程自建的文件中,应该放在lib文件中,并手动添加java build依赖
  • 注意使用过程中不是像GitHub上那样介绍的如此精简,需要自行添加sunApkPatch代码并适当添加捕获异常操作,防止Patch包引起Crash。
  • patchsample只是个简单的patch,如果需要增加比较复杂的patch,需要有依赖关系,为了缩小patch体积,这个依赖只能是部分依赖,所以推荐方式是将需要补丁的class文件打jar包引入依赖即可。

接下来我们看看具体的流程:

首先需要我们动态监测AOP环境

runPatchApk();

这里需要注意的是PatchMain.load()这个方法,该方法的主要用途是加载patch APK的所有类,并将实现IPatch的类添加到List中去,然后通过匹配加载的类或者类方法来实现非侵入式AOP。

public void runPatchApk() {
    if (android.os.Build.VERSION.SDK_INT == 21) {
        return;
    }
    if (!DexposedBridge.canDexposed(this)) {
        Log.d("Hotpatch", "This device doesn‘t support dexposed!");
        return;
    }
    File cacheDir = getExternalCacheDir();
    if (cacheDir != null) {
        String fullpath = cacheDir.getAbsolutePath() + File.separator + "PATCH_NAME.apk";
        PatchResult result = PatchMain.load(this, fullpath, null);
        if (result.isSuccess()) {
            Log.e("Hotpatch", "patch success!");
        } else {
            Log.e("Hotpatch", "patch error is " + result.getErrorInfo());
        }
    }
}

Patch实践

public class Activity extends BaseSherlockSubActivity implements
    OnNewIconUIRefreshListener {

    private void showDialog() {
    final AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle("Dexposed sample")
            .setMessage("Please clone patchsample project to generate apk, and copy it to \"/Android/data/PACKAGE_NAME/cache/PATCH_NAME.apk\"")
            .setPositiveButton("ok", new DialogInterface.OnClickListener() {

                public void onClick(DialogInterface dialog, int whichButton) {
                }
            }).create().show();
    }
}

假如我们上线的代码中如上所示,在弹层中出现文案bug,那么该如何热更新。

代码修复操作在Patch工程中,添加如下代码:

public class DialogPatch implements IPatch {

    @Override
    public void handlePatch(final PatchParam arg0) throws Throwable {
        Class<?> cls = null;
        try {
            cls = arg0.context.getClassLoader().loadClass("com.android.activity.Activity");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return;
        }
        DexposedBridge.findAndHookMethod(cls, "showDialog", new XC_MethodReplacement() {

            @Override
            protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
                final Activity mainActivity = (Activity) param.thisObject;
                AlertDialog.Builder builder = new AlertDialog.Builder(mainActivity);
                builder.setTitle("Fanli Dexposed sample").setMessage("The dialog is shown from patch apk!").setPositiveButton("ok", new OnClickListener() {

                    public void onClick(DialogInterface dialog, int whichButton) {

                        Class<?> clsInner;

                        try {
                            clsInner = arg0.context.getClassLoader().loadClass("com.android.activity.OutObject");
                        } catch (ClassNotFoundException e) {
                            e.printStackTrace();
                            return;
                        }

                        try {
                            OutObject outObject = (OutObject) clsInner.newInstance();

                            if (outObject.callFromOutMethod()) {
                                AlertDialog.Builder builder = new AlertDialog.Builder(mainActivity);
                                builder.setTitle("Fanli Dexposed sample").setMessage("com.android.activity.OutObject is Worked!")
                                        .setPositiveButton("ok", new OnClickListener() {

                                            @Override
                                            public void onClick(DialogInterface dialog, int which) {
                                                dialog.dismiss();
                                            }

                                        }).create().show();
                            }
                        } catch (InstantiationException e) {
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }

                    }
                }).create().show();
                return null;
            }
        });
    }

}

然后将这个patch APK 传到Server,在主APK中通过下载patch apk到指定目录,然后动态监测AOP环境并loadPatch即可实现热更新。

接下来如果应用到实际项目中需要完善的有以下几点:

  1. 动态监测AOP环境 (android server主动监测 patch包)
  2. 动态加载Patch文件 (更新pathc以后第一时间加载patch)

Patch测试结果:

基于以上实现方案测试的环境包括:

Dalvik 4.0-4.4均已经通过

目前 ART 5.0 以及以上版本 尚未通过。(待更新Native包和Jar包)

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-21 11:38:52

Android 热更新——非侵入AOP框架的相关文章

Dexposed:android免Root无侵入Aop框架

在网上看到了阿里推出的一个android开源项目,名为Dexposed, 是一个Android平台下的无侵入运行期AOP框架.旨在解决像性能监控.在线热补丁等移动开发常见难题,典型使用场景为: AOP编程 插桩 (如测试.性能监控等) 在线热补丁 SDK hooking以提供更好的开发体验 它基于ROOT社区著名开源项目Xposed改造剥离了ROOT部分,演化为服务于所在应用自身的AOP框架,并在Apache 2.0协议下开源. Xposed是XDA社区用户rovo89开发并管理的一个项目,它通

Android平台免Root无侵入AOP框架Dexposed使用详解

@author ASCE1885的 Github 简书 微博 CSDN 阿里巴巴无线事业部最近开源的Android平台下的无侵入运行期AOP框架Dexposed,该框架基于AOP思想,支持经典的AOP使用场景,可应用于日志记录,性能统计,安全控制,事务处理,异常处理等方面. 针对Android平台,Dexposed支持函数级别的在线热更新,例如对已经发布在应用市场上的宿主APK,当我们从crash统计平台上发现某个函数调用有bug,导致经常性crash,这时,可以在本地开发一个补丁APK,并发布

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

本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 Android热更新开源项目Tinker源码解析系类之三:so文件热更新 转载请标明本文来源:http://www.cnblogs.com/yyangblog/p/6252855.html更多内容欢迎star作者的github:https://github.com/LaurenceYang/artic

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

上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源热更新 Android热更新开源项目Tinker源码解析系类之三:so热更新 转载请标明本文来源:http://www.cnblogs

Android新技术学习——阿里巴巴免Root无侵入AOP框架Dexposed

阿里巴巴无线事业部最近开源的Android平台下的无侵入运行期AOP框架Dexposed,该框架基于AOP思想,支持经典的AOP使用场景,可应用于日志记录,性能统计,安全控制,事务处理,异常处理等方面. 针对Android平台,Dexposed支持函数级别的在线热更新,例如对已经发布在应用市场上的宿主APK,当我们从crash统计平台上发现某个函数调用有bug,导致经常性crash,这时,可以在本地开发一个补丁APK,并发布到服务器中,宿主APK下载这个补丁APK并集成后,就可以很容易修复这个c

Android热更新开源项目Tinker集成实践总结

前言 最近项目集成了Tinker,开始认为集成会比较简单,但是在实际操作的过程中还是遇到了一些问题,本文就会介绍在集成过程大家基本会遇到的主要问题. 考虑一:后台的选取 目前后台功能可以通过三种方式实现: 1.自己搭建后台布丁下发系统2.第三方提供的服务,目前如原微信simsun大神的个人tinkerpatch平台,目前出于内测阶段,暂时免费.后期应该会按下发量对app进行收费.3.腾讯Bugly提供的服务,提供了热更新的下发后台,集成到了bugly的升级sdk中.免费.根据公司的精神,我们选择

Android 热更新是如何实现的?

Android开发中,我们常常遇到热更新这个概念,而这个热更新具体是怎么实现的呢?今天在网上看到一个大神分享的热更新相关实现原理和实现代码,感觉灰常不错,分享给广大码农盆友look look . ClassLoader Android的基础语言是Java,而Java在运行时加载对应的类是通过ClassLoader来实现的,ClassLoader本身是一个抽象来,Android中使用PathClassLoader类作为Android的默认的类加载器. PathClassLoader又是什么?Pat

Android 美团Robust热更新 使用入门

Android热更新方案Robust 相信很多人都认识了解过 热修复.热更新.热补丁(对于这个技术也没有特别标准的一种叫法,下面我统一叫热更新),之后的一年里,各种热更新方案如雨后春笋般出现,比较耳熟能详的就有Nuwa.Tinker.Andfix 和 Dexposed 等等,他们之间的区别以及优缺点就不在这里讨论了,鉴于它们的实际使用和局限性,美团的开发团队就脑洞大开了. 就去年 Google 高调发布了 Android Studio 2.0,其中最重要的新特性Instant Run,实现了对代

客户端热更新框架之UI热更框架设计(下)

上一篇笔者介绍了关于什么是热更新,为什么需要热更新的技术文章.本篇就专门针对UI框架的热更新功能实现部分展开讨论,讨论的重点是热更新如何与UI框架进行结合? 现在笔者把设计“UI热更新框架”的整体设计与构建过程表述如下,最后附带源码工程的下载链接,供广大学员参考研究.如果大家有什么不明白的地方,欢迎大家在评论区进行讨论.   1:首先基于笔者以前设计的SUIFW 框架,做进一步功能完善.   完善UI框架对于复杂窗体的直接转向功能.为了小伙伴们能够更好的理解本技术,文章末尾特提供了下载链接供大家