What is componentization and plug-in
Modular:
It is to divide an APP into multiple modules, and each Module is a component. In the development process, we can make these components depend on each other or debug some components separately, but in the final release, these components are combined into an APK, which is componentized development. The plugin:
It is slightly different from componentized development. In plug-in development, the whole APP is divided into many modules, including one host and multiple plug-ins, and each module is an APK (each module of componentized is a lib). In the final packaging, the host APK and plug-in APK are separated or combined.
The difference between
To put it simply, componentization is divided into modules at compile time, while plug-in is divided into modules at run time. Generally, plug-in is used to dynamically fix bugs or dynamically update modules, which is relatively more black technology.
One, componentization
1. Android project components are generally divided into two types:
- Application component: The component itself can be run and packaged as an APK
- Lib component: a component that is part of an app and can be used by other components but cannot be packaged as an APK
Normally, an App can have multiple modules (modules), but usually only one module is set as Application and the others are set as Library. Componentized development means that every Module is up and running, so each module is set to Application during development and merged at release time.
2. Why componentization?
At a certain point in an Android project, compiling can be painful, ranging from a minute or two to five or six minutes. With the growth of APP business, it is normal for more and more modules and codes to exceed 100,000. At this time, we will encounter the following problems:
- A small change in the code of a module will have to compile the whole project, time-consuming and costly
- Common resources, services, and modules are too coupled
- Inconvenient test
3. Benefits of componentized development
Component-based development can effectively reduce the coupling degree of code modules, make the code architecture more clear, and modular compilation can effectively reduce the compilation time, of course, the total compilation time will not be reduced, but after the App modularization development of a module, only need to compile a specific module, can quickly compile and debug.
- Business modules are separated, and each module can be independently developed, compiled and run, which reduces the complexity of the project while decoupling.
- Resources and utility classes can be shared when developing individual modules.
- You can test against a single module without compiling the entire project during development and debugging.
- Multiple people can focus on their own business modules and develop a business as a single project.
- You can flexibly assemble and split service modules.
4. Main ideas of componentized development
It is to divide a Module into several modules, and the main App provides a unified entrance. Each Module after splitting depends on the shared Common dependency library. Through relevant configuration, each Module can run debugging independently or be used by the main App.
5. Steps of componentized development
- Create a New lib component, New → Module → Andorid Library, called BaseUtilLib, where we will put all the common utility classes, network encapsulation, and so on.
- Create a New lib component, New → Module → Andorid Library, called BaseReslLib, where we’ll put all the common resources, drawable, String, etc.
- Divide the APP into multiple modules according to requirements, such as by business and region, and then create Module modules respectively.
- Develop a module one by one, and each component can reference the BaseUtilLib and BaseReslLib public classes and resources in [1][2] steps. Components can be developed and tested separately.
- The component modules developed in the project are introduced into the app of the project, and then it can be published.
6. Here’s a simpler legend:
App: shell engineering module1: component 1 Module2: component 2 Common: third library, common tools, custom views, themes, etc
Two, plug-in
1. Why plug-in?
In the process of project development, it is inevitable that we will encounter changes in product requirements or bugs. In the traditional model, we first need to modify the code, then repackage the Apk, and send it to the company’s operations to the website or the app store, and users will update it when they open the app. But this model has several drawbacks:
- It takes a long time to go online, from modifying the code to updating the user;
- The cost of user update is high. Each user update needs to download the entire Apk package, which includes all the codes of an application and consumes a lot of user traffic.
- If there are some important updates, in order to ensure that users can update them, they also need to force updates, that is, users will quit the App if they do not update it after opening the App, which is extremely unfriendly to users.
- Another situation is that some large apps have many functions, such as Alipay and wechat, etc. If all these functions are crammed into one Apk, it will be a huge Apk, and users will have to wait for a long time to install or update the Apk.
Based on the above points, Android plug-in technology arises at the right moment. Plug-in technology can divide the whole huge Apk according to function modules, package different functions into different APKs, and then the main Apk of the application loads corresponding functions as required. Users only need to install the main Apk of the application. The main Apk is a shell that loads apKS for other functional modules on demand. Through this mode, not only the problem of huge Apk is solved, but also when a function module needs to change, it only needs to modify the corresponding function code, package the function Apk and update it. In this way, not only users can update it in time, but also the cost of update is small. However, we know that in Android, apK cannot run directly without installation, so to implement plug-in, we must make the host APK able to load and run the function APK.
2. Benefits of plug-in:
- The host and plug-in compile separately
- In concurrent development, both the host and the plug-in are APK, and the development is independent of each other, only requiring the host to give the plug-in a context
- Dynamic update plug-in, do not need to install, after downloading can be directly opened
- Download modules on demand
- Can solve the problem of method number or variable number overcrowding
3, plug-in standards:
Does every app run inside our host app? The answer is definitely not. We have to design a set of standards in the host app so that the plug-in app meets our standards in order to work. The main thing is that the plug-in app is not installed, so it has no context and requires our host to pass the context. Plug-in activities also have no life cycle, so our host also needs to manage the life cycle of the plug-in, as well as resources, layout, and so on.
4. Development of plug-in technology
Since around 2012, there have been a number of plug-in/componentized frameworks, each with its own flavor.
AndroidDynamicLoader: In July 2012, based on Fragement implementation, addAssetPath was used for the first time to read resources in the plugin by dynamically loading different Fragement interfaces.
Altas Technology Salon sharing: At the beginning of 2014, ali shared a technology salon, which mainly talked about the concept of Taobao Alta technology, but did not involve detailed implementation. At that time, it had been applied to Taobao client without open source.
Android – pluginmgr: In July 2014, primarily by manipulating Java virtual machine bytecode, by dynamically generating a plug-in class subclass such as the Four Major Components (which need to be declared in advance in the MANIFEST), To achieve plug-in functions (the latest has been changed into hook system some objects such as Instrumentation, ActivityThread, etc.)
Dynamic-load-apk: At the end of 2014, this framework was implemented in the way of proxy, without the underlying objects and methods of hook system. More representative, will be analyzed in detail later.
OpenAltas: April 2015, later renamed ACDD. This framework refers to many experiences of Taobao App, mainly the Hook idea (said to be decomcompiled code). At the same time, it is also proposed for the first time to solve the problem of resource ID conflict between plug-in and host by extending AAPT (Android Assert Packaging Tool).
Android-plugin-framework: In May 2015, many methods at the bottom of hook system were adopted, which felt that basically all the objects that could hook were hooked. The functions were relatively complete, but the so plug-in was not supported, so the compatibility was not good. At present, there are few practical applications.
DroidPlugin: In August 2015, it also hook a lot of Android system code, including local PMS, AMS, ActivityThread, Instrumentation, H and other objects, can load any App into the host to run. More representative, will be analyzed in detail later.
DynamicAPK: October 2015, referring to the design of ACDD mentioned earlier, and solving the resource problem by extending AAPT.
Small: at the end of 2015, is a relatively lightweight cross-platform plug-in framework, which is lighter than DroidPlugin. The basic principle is to hook the underlying object, and use Gradle scripts to solve the problem of resource conflict. You can configure URL to support plug-in jump.
TwsPluginFramework, in early 2017, also hook the underlying object method of the system, and solve the problem of resource conflict through appt.
Atlas: In March 2017, it is a dynamic componentized solution, also hooks many low-level object methods, supports SO, supports incremental patches and hot fixes, and is a single process framework.
VirtualAPK: At the end of June 2017, the basic principle is also the hook system underlying object method, support Gradle plug-in to complete the construction, more suitable for loading coupled plug-ins.
In early July 2017, the framework claimed to hook only one point, the ClassLoader, but in fact most of the work was shifted to JavaAssist at compile time, making it the first in the industry to propose “full plugins” (full features, full compatibility, full use). Detailed analysis will also be given later.
5. Basic knowledge related to plug-in
Basic knowledge mainly involved:
First, the Binder mechanism. Binder is the core of multi-process communication in Android system, and AIDL used in our daily development relies on Binder.
Second, the App packaging process. During a package operation, resource packaging, Dex generation, and signature are required. Among them, we need to pay attention to the principle of resource packaging, namely AAPT step, how to solve the resource ID conflict between the host and the plug-in can rely on AAPT to solve.
Third, the App installation process is also important. You also need to figure out how an APP is parsed, what files are generated and where they are stored after installation.
Fourth, the App startup process. The most common process is the familiar Activity startup process. If we understand the interaction and communication process of APP and AMS and other services, we can hook operation in some key points and realize plug-in in a stealthing way.
Fifth, the loading mechanism of resources. Android plug-in needs to control two places, one is the loading of the plug-in Dex, that is, how to load the classes in the plug-in Dex into memory; Another is resource loading, which ensures that the host and plug-in can load their own resources without conflict.
Sixth, is the Gradle build tool. Gradle build packaging can be involved in both the host and the plugin APK during the plug-in process, which is also important.