Overview:
The hot fix is actually very simple. It is easy to understand the difference between a bug-free apk and a bug-free apk. Generate a file ending with .apatch (used according to AndFix), and download the bug-free code from the Internet through a pre-fixed channel to replace the buggy one. The most important thing is to have a good user experience. If you follow the normal process, you need to fix the bug, package it, test it by the tester, and upload it to multiple application markets; Saves a lot of manpower and material costs.
1 The principle of hot repair
There are two types of Android class loaders: PathClassLoader and DexClassLoader, the parent class of both is BaseDexClassLoader, and the parent class of BaseDexClassLoader is ClassLoader
Among them, PathDexLoader is used to load system classes and application classes;
DexClassLoader is used to load some jar, apk, and dex files. In fact, jar and apk files actually load dex files
Hot repair principle: ClassLoader will traverse an array composed of dex files, and then load the dex files in it, we will insert the correct dex (dex where the repaired class is located) file in front of the array, when the loader loads the good dex file When the class file is loaded, the buggy class will not be loaded, and the hot repair will be implemented.
2 Examples of hot fixes
This case uses Alibaba's open source hot repair framework AndFix
1 First create an App class that inherits from Application
public class App extends Application { private static final String TAG = "App"; // Generated apatch file name public static final String APATCH_PATCH = "jiang.apatch"; private PatchManager mPatchManager; @Override public void onCreate() { super.onCreate(); //initialization mPatchManager = new PatchManager(this); String appversion=null; try { //If this place uses this method to get versionName appversion= getPackageManager().getPackageInfo(getPackageName(), 0).versionName; Log.i("aaa",""+appversion); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace (); } mPatchManager.init(appversion); //load apatch mPatchManager.loadPatch(); //directory of apatch file String patchFileString = Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator+APATCH_PATCH; Log.i("aaa","App:"+patchFileString); File apatchPatch = new File(patchFileString); if (apatchPatch.exists()){ Log.i(TAG, "Patch file exists"); try { mPatchManager.addPatch(patchFileString); } catch (IOException e) { Log.i(TAG, "Error patching"); e.printStackTrace (); } }else { Log.i(TAG, "Patch file does not exist"); } } }This is just a simulation. In fact, the real thing is to download the .apatch file through a fixed network channel and then update it.
2 Below is the code before and after the simulation repair
Before repair:
public class MainActivity extends AppCompatActivity { public Button mBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate (savedInstanceState); setContentView(R.layout.activity_main); mBtn = (Button) findViewById(btn); String patchFileString = Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator+APATCH_PATCH; Log.i("aaa",""+"MainActivity"+patchFileString); mBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "出现bug了", Toast.LENGTH_SHORT).show(); } }); } }After fix:
public class MainActivity extends AppCompatActivity { public Button mBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate (savedInstanceState); setContentView(R.layout.activity_main); mBtn = (Button) findViewById(btn); String patchFileString = Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator+APATCH_PATCH; Log.i("aaa",""+"MainActivity"+patchFileString); mBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "修复bug了", Toast.LENGTH_SHORT).show(); } }); } }
Packaged into apk files: bug.apk and nobug.apk (note that the apk file must be signed)
3 Then you need to use a tool for generating patches, apkapatch
The file directory is as follows
You need to put the signature file in the current file, use the command
apkpatch.bat -f nobug.apk -t bug.apk -o jiang -k mzbanner.jks -p 123456 -a w -e 123456
The meaning of the parameters is
-f represents the repaired apk -t represents the problematic apk -k represents the signature file -p represents the password of the signature file -a represents the alias -e represents the alias password
After opening it with the cmd command, it will generate a jiang folder and there will be a .apatch file generated in it
We can use decompilation to see what's inside
You can see that the class name ends with _CF, and the method name is annotated with @MethodReplace. In this way, you can find the classes and methods that need to be replaced.
4 Finally, look at the results
Interface to run bug.apk
When you put the jiang.apatch file into the specified SD directory, you will find a magical scene when you reopen the app
The above is a simple case of hot repair, welcome to correct