`
dengyin2000
  • 浏览: 1225000 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

使用Dexposed为你的安卓应用加上在线修复的能力。

阅读更多
移动客户端应用相对于Webapp的最大一个问题是做不到Online bug fix。如果全量发出去一个版本出现一个critical bug,紧急或者有安全漏洞的问题。这时你就会哭爹喊娘了。 如果是Webapp你可能最多花个1,2个小时紧急发布上线,但是app呢,打包,跪求市场发布几百个渠道,周么还发不了,app配置升级,你还不能配置强制升级, 就算配置提示升级,用户心里肯定想,老子他妈的前两天刚升级最新版,怎么又要升,而且升级要流量,这时候会去点升级按钮的用户肯定少得可怜。这时候你就能体会到server side发布的美好。所以这里有两个问题需要解决,1是安卓是否有能力做到打补丁,2是如何设计才能精确的把补丁推送到线上有问题的app。

1. 淘宝Dexposed框架https://github.com/alibaba/dexposed
如果你是撸机高手,你一定听过安卓神器Xposed框架,Xposed框架是一款可以在不修改APK的情况下影响程序运行(修改系统)的框架服务,基于它可以制作出许多功能强大的模块。什么你没听过,那赶紧谷歌下,你会发现你的安卓机可玩性大大提高。其实Xposed也是安卓的一个开源框架https://github.com/rovo89/Xposed https://github.com/rovo89/XposedBridge,Dexposed是啥?名字为啥这么像?Dexposed是安卓系统下的一款强大的无侵入性的AOP框架,当然他是基于Xposed的。之前在特卖会安卓代码中也有使用过Aspectj来写一些埋点代码,但是之后大家都渐渐的放弃了使用Aspectj来写埋点代码了, 这里有几个原因,一个Aspectj的有着特殊的语法,有入门门槛,你还要学习怎么使用Aspectj,另外一个原因是它有自己的编译器,app打包的时候还需要编译下Aspjectj代码,会注入他自己的代码,所以他是有侵入性的,而且编译耗时比较长,编译出来的代码你也是不能调试的。Xposed提供的是无侵入性的,而且AOP就是用的java代码。只要使用他的几个api即可。他有几个典型的使用场景:
  a. Classic AOP programming (大家常用的aop编程)
  b. Instrumentation (for testing, performance monitoring and etc.)  用于测试,性能监控等等
  c. Online hot patch to fix critical, emergent or security bugs   为安卓应用线上打补丁,用来解决一些严重的,紧急的或者安全漏洞的bug。
  d. SDK hooking for a better development experience

下面来看看如果写一些AOP的代码:
  1. Attach a piece of code before and after all occurrences of Activity.onCreate(Bundle). 
// Target class, method with parameter types, followed by the hook callback (XC_MethodHook).
    DexposedBridge.findAndHookMethod(Activity.class, "onCreate", Bundle.class, new XC_MethodHook() {
 
        // To be invoked before Activity.onCreate().
        @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
            // "thisObject" keeps the reference to the instance of target class.
            Activity instance = (Activity) param.thisObject;
 
            // The array args include all the parameters.
            Bundle bundle = (Bundle) param.args[0];
            Intent intent = new Intent();
            // XposedHelpers provide useful utility methods.
            XposedHelpers.setObjectField(param.thisObject, "mIntent", intent);
 
            // Calling setResult() will bypass the original method body use the result as method return value directly.
            if (bundle.containsKey("return"))
                param.setResult(null);
        }
 
        // To be invoked after Activity.onCreate()
        @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable {
            XposedHelpers.callMethod(param.thisObject, "sampleMethod", 2);
        }
    });


  2. Replace the original body of the target method.
DexposedBridge.findAndHookMethod(Activity.class, "onCreate", Bundle.class, new XC_MethodReplacement() {
 
        @Override protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
            // Re-writing the method logic outside the original method context is a bit tricky but still viable.
            ...
        }
 
    });


不过这个框架目前对android 5.0系统还不支持,他提供一个函数来检测你的android系统是否支持Dexposed,DexposedBridge.canDexposed(context)。 你需要把补丁包打包成一个apk, 然后通过下面的代码来加载补丁包:
File cacheDir = getExternalCacheDir();
 
        if(cacheDir != null){
 
            String fullpath = cacheDir.getAbsolutePath() + File.separator + "patch.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());
 
            }
 
        }


综上所述:安卓是可以通过淘宝的Dexposed框架来实现打补丁包的,不过目前这个项目还处理初期阶段对android 5.0系统支持有限,可能某些定制rom可能也会有问题。不过我相信这个框架会越来越好的,作者也说了会加上对5.0系统的支持。 需要深入的读者可以移步到Dexposed的github地址:https://github.com/alibaba/dexposed

2. 如何精确及时的推送补丁
要做到精确投放,就要考虑bug的产生有哪几种因素和那些维度。这样我们就能精准投放,而不是投放给了那些不需要补丁的用户,这样可能让没问题的用户打补丁之后反而产生问题。 以下是可能存在的一些因素和维度:
  1. 版本, 这个是最主要的因素, 我们经常需要就是为某个版本打补丁。
  2. android系统版本,某些安卓系统上有兼容性问题。
  3. 机型,某些机型有兼容性的问题。
  4. Rom,某些Rom才有的问题。
  5. 手机制造商, 比如小米。
  6. mid, 可能为某个或者某些用户打补丁。
  7. 渠道号, 为某些渠道的用户打补丁。
  8. 地区,为某些地区的用户打补丁。
  9. 分仓,为在某个分仓的用户打补丁。

当然上面的因素可以有一个或者多个合并。比如我要推送补丁到某个版本上的小米手机。我们在启动信息埋点中会上传用户的这些信息,后端就可以通过这些因素来定位要推送补丁的群体。我们会有一个补丁接口返回补丁的下载链接,补丁的匹配因素和这个补丁的crc或者md5。我们会把这些信息保存在客户端的数据库中,因为可能当用户升级到下一个版本时就不需要在加载这些补丁了。 所以我们在加载这些补丁的时候需要验证这个补丁是否适当当前app。当然如果想要及时推把补丁推送到客户端手中,我们可以使用push来推,而不是当用户打开app的时候来检测。下面是大概的流程。



注意: 这里漏了对patch apk验证的过程,这个很重要,首先对apk的md5验证, 然后最重要的需要对apk文件的签名进行验证,apk签名验证最好是放到ndk中实现, 后面的文章讲到具体实现的时候会讲到。

3. 代码示例
本代码示例主要是展示为以一个被除数不能为0这样的一个有bug的代码打补丁。有问题的代码如下:
public void doDivide(View view) {
    doDivideLogic();
}
 
public void doDivideLogic() {
    BigDecimal num1 = new BigDecimal(etNum1.getText().toString());
    BigDecimal num2 = new BigDecimal(etNum2.getText().toString());
    BigDecimal result = num1.divide(num2);             //这里num2不能为零。
    tvResult.setText(String.valueOf(result));
}

下面的代码为补丁包代码。我们主要是替换doDivideLogic的方法。补丁包这里为一个独立的android project项目,当然你需要把依赖的主项目的class文件打包为一个jar文件作为依赖。比如如下代码的MainActivity。补丁的代码如下:
/**
 * Created by denny on 2015/7/20.
 */
public class DivideLogicPatch implements IPatch {
    @Override
    public void handlePatch(PatchParam patchParam) throws Throwable {
        Class<?> cls = null;
        try {
            cls= patchParam.context.getClassLoader()
                    .loadClass("sample.dexposed.vip.com.dexposedsample.MainActivity");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return;
        }
        DexposedBridge.findAndHookMethod(cls, "doDivideLogic", new XC_MethodReplacement(){
 
            @Override
            protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
                Field etNum1Field = XposedHelpers.findField(MainActivity.class, "etNum1");
                EditText etNum1 = (EditText) etNum1Field.get(methodHookParam.thisObject);
                Field etNum2Field = XposedHelpers.findField(MainActivity.class, "etNum2");
                EditText etNum2 = (EditText) etNum2Field.get(methodHookParam.thisObject);
                Field tvResultField = XposedHelpers.findField(MainActivity.class, "tvResult");
                TextView tvResult = (TextView) tvResultField.get(methodHookParam.thisObject);
                String val = etNum2.getText().toString();
                if (val != null && "0".equals(val)) {      //被除数是否为0判断。
                    tvResult.setText("被除数不能为0");
                }else {
                    BigDecimal num1 = new BigDecimal(etNum1.getText().toString());
                    BigDecimal num2 = new BigDecimal(val);
                    BigDecimal result = num1.divide(num2);
                    tvResult.setText(String.valueOf(result));
                }
                return null;
            }
        });
    }
}

发现一个问题:在加载补丁包的时候需要调用DexposedBridge.canDexposed(context)方法才能加载成功。看了下源码,原来是在这方法里面加载so文件。
这个代码示例,我们是把补丁包app-patch.apk放到项目的assets,然后拷贝到sdcard中进行装载,如果是真实的项目的话应该是从网上下载补丁包,然后加载。代码可以从下面的链接下载:

DexposedSample.zip
DexposedSamplePatch.zip

Sample运行视频
  • 大小: 86.4 KB
分享到:
评论

相关推荐

    Android热修复demo

    本Android热修复demo将为你展示如何在实际项目中实现这一功能。 热修复通常基于动态加载和代码替换的原理,它分为两大部分:服务端和客户端。服务端负责存储修复补丁,并在需要时提供下载;客户端则负责接收并应用...

    dexposed框架jar包及so文件

    Dexposed框架是由阿里巴巴团队开发的一款强大的Android Hook框架,它允许开发者在不修改APK源码的情况下,对已安装的应用进行动态插桩,实现对应用程序功能的扩展或调试。本资源包含dexposed框架所需的jar包和so文件...

    Dexposed框架详解

    Dexposed是一款针对Android平台的运行时插件化框架,它允许开发者在不修改原生APK的情况下对应用进行功能增强或修复。这一框架的出现,为开发者提供了一种灵活的解决方案,尤其是在处理紧急的热修复问题时,无需用户...

    dexposed事例

    总之,Dexposed是一个强大的Android动态Hook工具,它为开发者提供了在运行时修改应用行为的能力。通过学习和掌握Dexposed,开发者可以实现诸如性能优化、功能增强、错误修复等多种复杂的任务,极大地提升了Android...

    在线热更新Dexposed框架

    总之,Dexposed为Android开发者提供了一种高效、灵活的在线热更新解决方案,通过动态插桩技术,可以在不打扰用户的情况下更新应用,提高迭代效率。同时,理解和掌握Dexposed对于提升Android开发技能和优化应用维护...

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

    在本文中,我们将深入探讨Dexposed框架的核心原理、应用场景以及如何使用它来增强Android应用的灵活性。 Dexposed框架是基于Dalvik虚拟机的,利用字节码插桩技术,在不改变原有应用代码的情况下,实现了对Android...

    热修复在代码中的应用

    热修复技术在移动应用开发中扮演着至关重要的角色,它允许开发者在不更新应用程序的情况下修复已发布的应用中的问题。这种技术极大地提高了用户体验,因为它避免了用户必须手动下载和安装更新的麻烦。本篇文章将深入...

    深入探索Android热修复技术-高清完整版

    热修复技术,也称为在线修复或动态修复,是Android应用在不重新安装或更新的情况下,能够修复程序错误或添加新功能的技术。它极大地提升了用户体验,减少了应用维护的复杂性。 本书的作者通过深入浅出的讲解,旨在...

    一加8 root magisk dexposed

    在Android世界中,"一加8 root magisk dexposed" 是关于高级用户操作的主题,涉及到对一加8手机进行root权限获取、安装Magisk框架以及使用 Dexposed 模块的内容。这里将详细解释这些概念及其相关知识。 1. **Root...

    Android_热修复 实战视频(kotlin)

    在Android应用开发中,热修复(Hot Fix)是一种重要的技术,它允许开发者在不更新应用的情况下修复线上出现的bug或缺陷。本实战视频教程聚焦于使用Kotlin语言实现Android热修复,通过具体案例帮助开发者理解和掌握这...

    android 应用开发全程实录(裴佳迪)源代码reality+各章节

    19. **热修复与插件化**:了解如何使用AndFix、Dexposed等技术进行应用的热修复,以及插件化的实现原理。 20. **Android Studio调试技巧**:学会使用Logcat、Profiler等工具进行问题定位和性能分析。 通过阅读...

    Android热修复Tinker

    Tinker相对于其他热修复框架(如AndFix、Dexposed等)的优势在于其全面的修复能力,支持资源、SO库以及对Java和Native层的修复。此外,Tinker具有良好的兼容性和稳定性,能够处理复杂的修复场景。 **5. 注意事项** ...

    蘑菇街Android热修复探索之路PDF版本

    热修复技术是Android开发领域中一项用于快速修复线上应用问题而不需重新发布版本的重要技术。从描述来看,本文主要介绍业界各种热修复方案的原理及其优缺点,同时详细探讨了蘑菇街从QZone方案到ASM注入方案(Aceso)...

    Android应用案例开发大全源代码(上)

    15. **热修复和插件化技术**:可能包含对ApkPatch、AndFix或Dexposed等热修复或插件化框架的应用。 通过研究这个源代码合集,开发者可以加深对Android应用开发的理解,掌握实际开发中的最佳实践,并为自己的项目...

    Android应用源码-聊天通讯类安卓源代码(12例).zip

    这份"Android应用源码-聊天通讯类安卓源代码(12例)"的压缩包为我们提供了宝贵的参考资料,可以帮助开发者深入理解如何构建这类应用。下面,我们将详细讨论这些源代码中的关键知识点。 1. **网络通信技术**:在...

    Android thinker demo

    "Android thinker demo" ...总的来说,"Android thinker demo"是一个有价值的资源,它可以帮助开发者掌握Android应用的热修复技术,提升故障响应能力,同时也可以深入了解Android应用的运行机制和动态代码加载的概念。

    热修复(资源代码修复)

    7. **其他热修复框架**:除了QQ空间的方案,还有如Tinker、AndFix、Dexposed等知名的Android热修复框架,它们各有特点,开发者可以根据项目需求选择合适的技术栈。 总的来说,热修复技术是现代移动应用不可或缺的一...

Global site tag (gtag.js) - Google Analytics