PrefaceThe plug-in technology originally originated from the idea of running apk without installation. This installation-free apk can be understood as a plug-in. Apps that support plug-in can load and run plug-ins at runtime, so that some uncommon functional modules in the app can be made into plug-ins, which can reduce the size of the installation package on the one hand and realize the dynamic expansion of app functions on the other hand; Today we will talk about plug-in 1. Introduction to plug-in1. Introduction to plug-inIn the Android system, applications exist in the form of Apk, and applications need to be installed before they can be used. But in fact, the way to install applications in the Android system is quite simple, which is actually to copy the application Apk to different directories of the system and then unzip it; Common application installation directories are:
The composition of Apk, a common Apk will contain the following parts:
In fact, after opening the application, the Android system only opens a process, then uses ClassLoader to load classes.dex into the process and executes the corresponding components; Then you may wonder, since Android itself also uses a reflection-like form to load code execution, why can't we execute the code in an Apk? This is actually the purpose of plug-in, which allows the code in the Apk (mainly Android components) to run without installation, which can bring a lot of benefits. The most obvious advantage is actually hot update and hot repair through the network; 2. Difficulties of plug-in technology
3. Parent delegation mechanismClassLoader calls the loadClass method to load the class. The code is as follows:
It can be seen that when ClassLoader loads a class, it first checks whether it has loaded the class. If it has not loaded it, it will first ask the parent loader to load it. If the parent loader cannot load the class, it will call its own findClass method to load it. This mechanism avoids repeated loading of classes to a large extent. 2. Detailed explanation of plug-in1. ClassLoader InjectionIn short, in a plug-in scenario, there will be multiple ClassLoaders in the same process:
We call this process ClassLoader injection; After the injection is completed, all classes from the host are loaded using the host's ClassLoader, and all classes from the plugin Apk are loaded using the plugin ClassLoader; Due to the parent delegation mechanism of ClassLoader, the system classes are not affected by the class isolation mechanism of ClassLoader, so the host Apk can use the component classes from the plug-in in the host process; 2. Runtime ContainerAfter the ClassLoader is injected, you can use the classes in the plugin Apk in the host process. However, we all know that Android components are started by system calls. Components in an uninstalled Apk are not registered with AMS and PMS. It is like if you directly use startActivity to start a component in a plugin Apk, the system will tell you that it cannot be found. Our solution is very simple, namely runtime container technology. In simple terms, it is to embed some empty Android components in the host Apk. Taking Activity as an example, I preset a ContainerActivity extends Activity in the host and register it in AndroidManifest.xml; What it has to do is very simple, that is, to help us as a container for the plug-in Activity. It accepts several parameters from the Intent, which are different information about the plug-in, such as:
When loading is complete, ContainerActivity does two things:
We can complete the first step by overriding the lifecycle method of ContainerActivity, and the second step is to define a PluginActivity. Then, when writing the Activity component in the plugin Apk, we no longer integrate android.app.Activity, but integrate it from our PluginActivity. Later, we can automate this operation by replacing the bytecode. I will explain why later. Let's look at the pseudo code first;
But the principle is probably as simple as this. Starting the plug-in component requires relying on the container. The container is responsible for loading the plug-in component and completing two-way forwarding, forwarding the life cycle callbacks from the system to the plug-in component, and forwarding the system calls from the plug-in component to the system. 3. Resource InjectionThe last thing to talk about is resource injection, which is actually quite important. Android application development actually advocates the concept of separation of logic and resources. All resources (layout, values, etc.) will be packaged into Apk, and then a corresponding R class will be generated, which contains reference ids to all resources; It is not easy to inject resources. Fortunately, the Android system has left us a way out. The most important ones are these two interfaces:
What we need to do is to use these two methods to create a plugin resource instance when loading the plugin Apk in the above ContainerActivity#onCreate. Specifically, we first use PackageManager#getPackageArchiveInfo to get the PackageInfo of the plugin Apk. After we have the PackageInfo, we can assemble an ApplicationInfo ourselves, and then create a resource instance through PackageManager#getResourcesForApplication. The code is roughly like this:
After getting the resource instance, we need to merge the host's resources with the plugin resources and write a new Resources class to complete the automatic proxy in this way:
Then, after ContainerActivity completes loading the plug-in component, we create a Merge resource and then override ContainerActivity#getResources to replace the obtained resources:
This completes the injection of resources 4. Resolving resource conflictsThe merged resource processing method will introduce resource conflicts because the resource IDs in different plug-ins may be the same, so the solution is to make different plug-in resources have different resource IDs; The resource id is represented by an 8-bit hexadecimal number, expressed as 0xPPTTNNNN. The PP segment is used to distinguish the package space. By default, it only distinguishes between application resources and system resources. The TT segment is the resource type. The NNNN segment increases from 0000 in the same APK. SummarizeThere are actually many plug-in frameworks on the market, such as Tecent's Shadow, Didi's VirtualApk, and 360's RePlugin. They each have their own strengths, but they are generally similar; Their general principles are actually similar. When running, there will be a host Apk running in the process. The dormitory Apk is the actual installed application. The host Apk can load the components and codes in the plug-in Apk to run, and the plug-in Apk can be hot-updated at will; |
>>: Xiaomi stores are everywhere, but why are there so few Apple stores?
Every time when various Internet celebrities shar...
Every year after the winter solstice, people alwa...
1. SB Admin 2 Details & Download 2. Adm...
This article is selected from the Hunzhi comic se...
1.Q: The business entity or special qualification...
There is no doubt that global smartphone shipment...
Course Catalog ├──001 Opening Ceremony.ts 170.53M...
According to the latest report released by TrendF...
According to foreign media reports, although Chin...
I just saw an article analyzing Changyu, pointing...
Not long ago, a friend of mine who works in the c...
The 2023 Nobel Prize in Chemistry was awarded for...
This is the best of times, it is the worst of tim...
In our daily lives, whether we are browsing our p...
After releasing iOS 14.7 last week, Apple has sto...