Android Hot FIX: Andfix and hotfix, comparison and implementation of two schemes

Source: Internet
Author: User

Andfix and hotfix are two types of Android hot fix frameworks.

Android Thermal Repair Technology I look at the earliest should be the QQ Space team solution, and then really need to carefully investigate, now the program, Ali has two dexposed and andfix framework, Since the previous one does not support more than 5.0 Android system, so the Ali system of the program we look at Andfix just fine. The hotfix framework is the implementation of the QQ space team theory mentioned above. This paper aims to write the implementation scheme, the piggyback principle.

Andfix Introduction

Frame Official website: Https://github.com/alibaba/AndFix
The introduction is written in English, so attach the translation URL:
http://blog.csdn.net/qxs965266509/article/details/49802429

Using Android Studio development, introduce the following:

compile‘com.alipay.euler:andfix:0.4.0@aar‘
Principle

The following is a repair process diagram for us to understand better.

As you can see, the fix for Andfix is method-level and replaces the method with the bug.

Make Patches

The official has to use the way, but relatively brief, so there will be some changes. My idea is to make a patch and then put it on the server, the client downloads the patch to the specified folder, and then fixes it.
The first to have patches of production tools, the official is also ready for us: here
After decompression, we put the pre-repair apk and the repaired Apk,keystore (for convenience, I use the debug KeyStore) into this folder, as follows:

The need to make a patch file with a command, which requires a pre-repair apk and a fixed apk to do the comparison, the command meaning is as follows:

Command: Apkpatch.Bat- F New.apk- TOld.apk- oOutput1- kDebug.KeyStore- PAndroid -AAndroiddebugkey- eAndroid- F <New.apk>: New version- T <Old.apk>: Old version- o <Output>: Output Directory- k <KeyStore>: KeyStore used for packaging- P <Password>: KeyStore's password -A <Alias>: KeyStore User Alias- e <Alias password>: KeyStore User alias password


Then a suffix is generated in the Outputdic. Apatch file:

Renamed to Out.apatch, this is our patch.

Hit patch

How do I use patches? The same steps as putting an elephant in a refrigerator.
The following code is directly on:
First step: Put the patch on the server.
For simplicity, with the XAMPP, write a snippet of PHP code, play the function of the download can be.

<?php$file _name="Out.apatch";//files that need to be downloadedDefine"Spath","/files/");//relative path for storing files$file _sub_path=$_server[' Document_root '];//Absolute address of Web site root directory$file _path=$file _sub_path. spath.$file _name;//file absolute address, i.e. front three connections//Determine if the file existsif(!file_exists ($file _path)){Echo "The file does not exist";return;}$fp= fopen ($file _path,"R");//Open File$file _size= FileSize ($file _path);//Get file size/** required to download the file header*/Header"Content-type:application/octet-stream"); Header ("Accept-ranges:bytes"); Header ("Accept-length:".$file _size); Header ("Content-disposition:attachment;filename=".$file _name);$buffer=1024x768;$file _count=0;//Return data to the browser while(!feof ($fp) &&$file _count<$file _size){$file _con= Fread ($fp,$buffer);$file _count+=$buffer;Echo $file _con;//If it does not echo, it will only be downloaded to 0 bytes of file}fclose ($fp);?>

Step two: Download and patch.
Back to Android, in our application:

publicclass App extends Application {    @Override    publicvoidonCreate() {        super.onCreate();        YuanAndfix.inject(this);    }}

Among them, the Yuanandfix class:

 Public  class yuanandfix {     Public Static FinalString Apatch_path ="Out.apatch"; Public Static void Inject(FinalContext context) {FinalPatchmanager Patchmanager =NewPatchmanager (context); Patchmanager.init (Buildconfig.version_code +"");//current versionPatchmanager.loadpatch ();NewThread (NewRunnable () {@Override             Public void Run() {Httpdownload httpdownload =NewHttpdownload (); Httpdownload.downfile ("http://192.168.1.12/download.php", Context.getdir ("Patch", context.mode_private). GetAbsolutePath () +"/", Apatch_path);Try{String Patchpath =context.getdir ("Patch", context.mode_private). GetAbsolutePath () +"/"+apatch_path; File File =NewFile (Patchpath);if(File.exists ())                        {Patchmanager.addpatch (Patchpath); Toast.maketext (Context,"Patch Complete", Toast.length_short). Show (); }Else{Toast.maketext (context,"Failed", Toast.length_short). Show (); }                }Catch(Exception e)                {E.printstacktrace ();    }}). Start (); }}

This way, the hot fix is done, and this example is the Click button that pops up the toast display text, before the fix is

Toast.makeText(MainActivity.this,"bug",Toast.LENGTH_SHORT).show();

After the repair is:

Toast.makeText(MainActivity.this,"fixed",Toast.LENGTH_SHORT).show();

The above is the use of Andfix, after my experiment, the limitation of using this framework is that the global variables cannot be modified, not add new methods, but can be modified on the existing methods, plus local variables. From this point of view, Andfix actually requires that we just modify the bug inside the method and not make changes on a large scale. If we feel that this repair does not meet the repair requirements, then you can see the other, less limited heat repair program.

Hotfix principle

Official website: Https://github.com/dodola/HotFix
Before using this framework, I would like you to take a look at the principle, which is very helpful to the implementation of the latter.

Let me briefly explain the principle.

Plug multiple dex files into the app's ClassLoader android load, if there are more than one Dex file has the same class, will load the preceding class, so this hotpatching principle is to replace the problematic class, the need to put the class to the front, to achieve the purpose of HotPatching.

But there is a problem, we want to replace the class, can not be played on the class_ispreverified flag, otherwise the return is wrong, so the difficulty of this solution is how to let the class that want to be repaired is not to be played on the class_ispreverified flag. So, the hack gods of the gods come, first make a DEX package, and then give us the constructor of the class that we want to fix, inject this DEX package, in fact, a class that outputs this DEX package:
System.out.println (Dodola.hackdex.AntilazyLoad.class);
This way, the class we want to fix is not marked with the CLASS_ISPREVERIFIED flag, and the patch can be loaded.

Framework

The use of this framework, whether in configuration, or patch generation, are relatively troublesome, although there is a similar framework Nuwa did the automation of this piece, but it is said that some pits are not filled, so decisively use this hotfix framework. Frame download, let's look at the structure first.

The app is the main project;
BUILDSRC is the gradle task,gradle compiler command is composed of multiple tasks, which is to be blunt is gradle to compile the program in accordance with these task sequence to execute the command.
Hackdex inside an empty class, the purpose in order to let the compiler pass, so that the main project class is not to be played on the class_ispreverified flag.
Hotfixlib is a fixed tool class.

Then, let's see how they work together.
The first is the Build.gradle file of the main engineering app, which has two more pieces of code:

task(‘processWithJavassist‘) << {    file(‘build/intermediates/classes/debug‘)//项目编译class所在目录    dodola.patch.PatchClass.process(classPath, project(‘:hackdex‘).buildDir            ‘/intermediates/classes/debug‘)//第二个参数是hackdex的class所在目录}

And

applicationVariants.all { variant ->        variant.dex.dependsOn << processWithJavassist //在执行dx命令之前将代码打入到class中    }

This is through javassist, the construction method of the main engineering class is injected
System.out.println (Dodola.hackdex.AntilazyLoad.class);
Antilazyload.class in the app's assets, the program will be copied to the SD card after running, mainly to let the main project class is not marked Class_ispreverified.

Make Patches

A patch is a collection of class files that you want to replace, a patch-making process reference
Https://github.com/dodola/HotFix;
The classes used here are advanced here:

Then put the repaired class into a folder, and the folder path is the same as the package name of your original class. Such as:
Like the Bugclass.class class, put it in a folder like this.

Then execute the command:

This generates a Path.jar under the D disk, and then the jar is made into Dex, because the DX is used, and this DX is in our SDK toolkit, so I copy this path.jar to the SDK Toolkit, using the DX command


The Path_dex.jar will then be generated, and this is our patch file.

Hit patch
 Public  class hotfixapplication extends application {    @Override     Public void onCreate() {Super. OnCreate (); File Dexpath =NewFile (Getdir ("Dex", Context.mode_private),"Hackdex_dex.jar"); Utils.preparedex ( This. Getapplicationcontext (), Dexpath,"Hackdex_dex.jar"); Hotfix.patch ( This, Dexpath.getabsolutepath (),"Dodola.hackdex.AntilazyLoad");Try{ This. getClassLoader (). LoadClass ("Dodola.hackdex.AntilazyLoad"); }Catch(ClassNotFoundException e)        {E.printstacktrace (); }    }}

Then the download and patch

      Switch(Item.getitemid ()) { CaseR.id.action_fix: {NewThread (NewRunnable () {@Override                     Public void Run() {String URL ="http://192.168.1.12/download.php"; Httpdownload httpdownload =NewHttpdownload ();Final intFlag = httpdownload.downfile (URL, mainactivity. This. Getdir ("Dex", context.mode_private). GetAbsolutePath () +"/","Path_dex.jar"); Hotfix.patch (mainactivity. This, Mainactivity. This. Getdir ("Dex", context.mode_private). GetAbsolutePath () +"/"+"Path_dex.jar",""); Runonuithread (NewRunnable () {@Override                             Public void Run() {String filestate=NULL;if(flag==0) {filestate ="Download Complete"; } ;if(flag==1) {filestate ="File already exists"; }if(flag==-1) {filestate ="Download Error"; } toast.maketext (mainactivity. This, Filestate, Toast.length_short). Show ();                    }                        });            }}). Start (); } Break; CaseR.id.action_test:loadbugclass Bugclass =NewLoadbugclass (); Toast.maketext ( This,"Test call Method:"+ bugclass.getbugstring (), Toast.length_short). Show (); Break; }

It is important to note that if a class is called once, it will take effect the next time the program is started. So if we order the test first, then click Download, then we need to restart the program (background kill), the patch will take effect.

Manual injection

The above on the prevention of the class is playing class_ispreverified logo, although good, but there are limitations, must be compiled with Gradle, but also to understand the byte code injection, if we are developed with eclipse, it is not used, in fact, we have a way, is to manually add that line to the class.
SYSTEM.OUT.PRINTLN (Dodola.hackdex.AntilazyLoad.class) code, as long as the compilation is guaranteed to pass. So here we are, we're building a new project, Androidstudio,

Look at Main, we created a new hack folder, inside put a hack.jar, there is only such a class:

publicclass AntilazyLoad {}

Then, in our main engineering app, the class construction method, adding
System.out.println (Dodola.hackdex.AntilazyLoad.class), this line of code, to achieve the purpose of manual injection, there is no need for those complex task code, byte code injection and other operations. So if you're using Eclipse, the directory is like this.

This jar package will not be packaged into the app, which is to let the compiler pass, the real antilazyload.class is actually the Hack_dex.jar under the project's assets package.
The above methods are fully feasible, especially the manual injection method, which can solve most of the developers will not use the heat more trouble. This is the way I read this article.
Ps:
1, this framework can not be modified with the final decoration of things, remember.
2, the official website gives the patching code

HotFix.patch(this, dexPath.getAbsolutePath"dodola.hackdex.BugClass");

In this case, it is unreasonable, the third parameter actually to pass the bug class name, we can not predict which class will occur the bug, so I changed to this

HotFix.patch(this, dexPath.getAbsolutePath"");

The third parameter is not to be tested.

Summarize

Compared to the two solutions, Ali's andfix more attention to change the details of the bug, although it is from the native layer to do the operation, but the framework is well packaged, we use it very simple, and has updated maintenance, it is said that the Ali Department of the app is intended to use this. If we're just developing an app that doesn't have big changes, doesn't heat more global variables and doesn't add methods, then the framework is the first choice.
But sometimes we may develop an SDK, such as the Friend League SDK, or want to heat more global variables, add methods, then Andfix can be said to be used, so this time hotfix is a better choice.
Download point here
Andfixdemo
Hotfixdemo
Service-Side PHP code

Android Hot FIX: Andfix and hotfix, comparison and implementation of two scenarios

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.