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

2024-09-04 18:18
文章标签 android 更新 框架 aop 侵入

本文主要是介绍Android 热更新——非侵入AOP框架,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

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

简要说明:

该框架基于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 implementsOnNewIconUIRefreshListener {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 {@Overridepublic 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() {@Overrideprotected 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() {@Overridepublic 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包)

框架下载地址:http://download.csdn.net/detail/u013334392/9629585

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

这篇关于Android 热更新——非侵入AOP框架的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1136672

相关文章

Android协程高级用法大全

《Android协程高级用法大全》这篇文章给大家介绍Android协程高级用法大全,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友跟随小编一起学习吧... 目录1️⃣ 协程作用域(CoroutineScope)与生命周期绑定Activity/Fragment 中手

AOP编程的基本概念与idea编辑器的配合体验过程

《AOP编程的基本概念与idea编辑器的配合体验过程》文章简要介绍了AOP基础概念,包括Before/Around通知、PointCut切入点、Advice通知体、JoinPoint连接点等,说明它们... 目录BeforeAroundAdvise — 通知PointCut — 切入点Acpect — 切面

MySQL 数据库表操作完全指南:创建、读取、更新与删除实战

《MySQL数据库表操作完全指南:创建、读取、更新与删除实战》本文系统讲解MySQL表的增删查改(CURD)操作,涵盖创建、更新、查询、删除及插入查询结果,也是贯穿各类项目开发全流程的基础数据交互原... 目录mysql系列前言一、Create(创建)并插入数据1.1 单行数据 + 全列插入1.2 多行数据

linux安装、更新、卸载anaconda实践

《linux安装、更新、卸载anaconda实践》Anaconda是基于conda的科学计算环境,集成1400+包及依赖,安装需下载脚本、接受协议、设置路径、配置环境变量,更新与卸载通过conda命令... 目录随意找一个目录下载安装脚本检查许可证协议,ENTER就可以安装完毕之后激活anaconda安装更

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

解决若依微服务框架启动报错的问题

《解决若依微服务框架启动报错的问题》Invalidboundstatement错误通常由MyBatis映射文件未正确加载或Nacos配置未读取导致,需检查XML的namespace与方法ID是否匹配,... 目录ruoyi-system模块报错报错详情nacos文件目录总结ruoyi-systnGLNYpe

Nginx进行平滑升级的实战指南(不中断服务版本更新)

《Nginx进行平滑升级的实战指南(不中断服务版本更新)》Nginx的平滑升级(也称为热升级)是一种在不停止服务的情况下更新Nginx版本或添加模块的方法,这种升级方式确保了服务的高可用性,避免了因升... 目录一.下载并编译新版Nginx1.下载解压2.编译二.替换可执行文件,并平滑升级1.替换可执行文件

SQL Server跟踪自动统计信息更新实战指南

《SQLServer跟踪自动统计信息更新实战指南》本文详解SQLServer自动统计信息更新的跟踪方法,推荐使用扩展事件实时捕获更新操作及详细信息,同时结合系统视图快速检查统计信息状态,重点强调修... 目录SQL Server 如何跟踪自动统计信息更新:深入解析与实战指南 核心跟踪方法1️⃣ 利用系统目录

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.

Python Web框架Flask、Streamlit、FastAPI示例详解

《PythonWeb框架Flask、Streamlit、FastAPI示例详解》本文对比分析了Flask、Streamlit和FastAPI三大PythonWeb框架:Flask轻量灵活适合传统应用... 目录概述Flask详解Flask简介安装和基础配置核心概念路由和视图模板系统数据库集成实际示例Stre