1. Introduction

Starting from this chapter, we will start with the architecture design scheme of Alipay client, and subdivide and disassemble the specific implementation of alipay client in “container framework design”, “network optimization”, “performance startup optimization”, “automatic log collection”, “RPC component design”, “mobile application monitoring, diagnosis, positioning” and so on. Lead you to further understand the iteration and optimization process of Alipay’s client architecture.

This section will introduce the basic idea of alipay Android container framework design.

1.1 Development Background

As Android applications become more powerful and complex, here’s what happens:

  • The code and resources of Android program are more and more, the size of APK file is bigger and bigger, and Android program is more and more complex;
  • Parallel development based on traditional architectural patterns becomes more difficult as applications iterate, projects expand, and the number of teams and team members increases simultaneously.

In addition, mobile clients often face the challenges of dynamic development; Operation and maintenance requirements such as emergency Bug repair; At the same time, there are also some online operation needs, such as dynamic advertising, push access activities, etc. It would be a traditional developer’s nightmare to have a client release every time there is an o&M or operational requirement.

Android developers are keenly aware of the importance of a robust, scalable, and massively parallel client-side development framework for platform-level client apps. In fact, the robustness and extensibility of the client framework design often makes it easier for Android client developers to meet these requirements and solve these problems with less effort.

Then, as a platform level Android client App how to carry out framework design, in order to meet the ever-changing mobile Internet era of difficulties and needs?

1.2 Issues facing platform-level client frameworks

No. The problem describe
1 Project complexity is high, development, compilation, testing, integration are very difficult Alipay App code 200W line +
2 Platform-level apps have a large number of internal microapplications (teams) and high concurrent development requirements Up to dozens of internal applications
3 APK size large Alipay App60+M, cause in some manufacturers Rom installation failed
4 There are various problems with the online version For example, after the release, the UCSDK is exposed to security vulnerabilities by the Cloud platform
5 Online activity operation requirements During the Spring Festival red envelope scanning activity, the plan should dynamically push the new SO file to the client

The bottom line is that a platform-level client framework must address the two core issues of modularity and dynamism.

(We’ll focus on modularity in this article, and we’ll analyze the dynamic capabilities in other articles.)

1.3 Framework design principles

To solve the modularity problem above, we design the client framework by following the following principles:

  • According to the basic technology level, client business line and other principles, the client application is modular split.
  • Each module is developed, maintained, tested, and integrated by a small team or individual.
  • Modules should be completely decoupled. Modules can be dependent on each other through interfaces.
  • Each module can be hot-swappable, and the insertion and removal of a single module does not affect the compilation and operation of the overall project.

2. Quinox profile

The Quinox client framework is an implementation of the OSGi-like (like-as) framework. The term Quinox comes from Equinox, an implementation of the well-known OSGi framework.

Client apps based on this framework are built by building blocks, which are called bundles.

3. The Bundle is introduced

3.1 What is a Bundle

A Bundle is the basic modular unit of the OSGi specification and is a completely different concept from android.os.Bundle in Android. A Bundle in OSGi refers to the basic unit of a Java application, a modular unit (Jar format), which is also the building block mentioned in the Quinox introduction above. Applications based on the Quinox container framework are also made up of bundles (THE APK format).

This chapter will describe the Bundle form from three different phases of project development:

period form
Development period Bundle engineering
Build period Bundle package
The integration period Integrate the client’s Bundle baseline

3.2 Bundle engineering

In regular Android project development, there are usually two (two-level) types of code engineering

Project type Library Application
Project output Aar Apk

There are three (three-level) types of Android projects and code projects based on the Quinox container framework

Project type Library Project package Application (test/install /Final APK)
Project output Aar Apk(.jar) Apk

There are three things we need to know about the Bundle project:

  • The Bundle project is very similar to a regular Android Application project: it also has multiple libraries (Android Modules) inside it; Its output is also in APK format.
  • Although the Bundle file is essentially in the APK format, the APK does not run. Also, when the Bundle project is deployed to the MVN repository, its suffix is changed to.jar.
  • The Quinox container-based Application project (called a Portal project) is a process of combining bundles (APKs) into a single APK (Final). This is a merge, not a compile, so generating the final APK will be very fast because the compilation is distributed across bundles. Client programs based on Quinox containers require the mPaaS custom build tool (that is, the packaging plug-in).

For a diagram of the Bundle project, see:

3.3 Bundle package

As mentioned above, the output of the Bundle project is also an APK file.

In the OSGi specification, bundles have many properties. The APK output from a Bundle project differs from a regular APK in that the mPaaS plug-in generates a special file containing all the Bundle properties for the container to read.

In addition to the APK file, the build results of the Bundle project include:

  • AndroidMannifest.xml
  • Bundle interface package (can be thought of as a JAR package that contains and exposes the interface classes provided by the Bundle)
  • mapping.txt

Bundle files, when built, are typically deployed to local/remote MVN repositories for reference by other Bundle projects or integrated by Portal projects.

3.4 Bundle baseline

As mentioned earlier, building a Final APK is essentially a process of merging many Budnle APKs into a Final APK, and these Bundle APKs are stored in the MVN repository.

Therefore, we call the collection of GAV (GroupId, ArtifactId, Vesion) of these bundles the baseline.

When a team/individual starts a new feature in a Bundle and tests it to release status, it updates the version number in the baseline. We refer to this process as forward baselines. We believe that the APK printed in the baseline is stable and operational; Project packages should not be baselined without stable bundles.

The Bundle baseline mechanism can well isolate the interaction between modules, ensure the harmony and stability of the development environment between different teams, and achieve the original intention of our previous design, so it can well support the parallel development of multiple teams.

3.5 Bundle Properties and Configuration Methods

For the Bundle property, refer to OSGi’s Bundle property. The Bundle property defined in the Quinox container box is much simpler.

The following table lists all the Bundle properties and their configuration methods:

The name of the instructions The configuration method
Bundle-Name The name of the Bundle, which exists as the key value. Bundles with the same name cannot exist on the same client APK The GroupId and ArtifactId of the Bundle project GAV are generated by the mPaaS plug-in according to certain rules.
Bundle-Version The version number of the Bundle. The interface packages of each Bundle must be backward compatible with the API version. Generated by the mPaaS plug-in according to the Version in the Bundle project’s GAV
Init-Level Have been abandoned Set this parameter to 1
Package-Name Have been abandoned Set this parameter to “”
Component-Name The Android Component declared in the Bundle. This, like the export-Pacakges property, is the entry class to the Bundle. Generated by the mPaaS plug-in according to the Activity, Service, BroadcastReceiver, ContentProvider and so on defined in the AndroidManifest.xml file
Package-Id The packageID of the Bundle project’s resources. See Section 4.2 for technical details The packageId property must be set by the developer in the Bundle project. The value is set to [27, 127], 127 if no resources are available, and 27 if the Bundle is the root of the Bundle dependency tree.
Contains-Dex Does the Bundle contain code (classes.dex)? The mPaaS plug-in determines whether the Bundle file contains the classes.dex node. Note: Statically linked bundles are merged into the main APK by classes.dex, so this property will be fixed to false
Contains-Res Does the Bundle contain resources (resources.arsc)? The mPaaS plug-in determines whether the Bundle contains the resources.arsc file.
Native-Library Native so (lib/ XXX /libxxx.so) native so (lib/ XXX /libxxx.so) It is determined by the mPaaS plug-in according to the native SO file in the Bundle file. Note: All so files in the Bundle will merge into Final APK when building Final APK, so this property will be corrected to null
Required-Bundle List of bundles that this Bundle depends on: in Budnle-Name@Bundle-Version format. This property is generated by the mPaaS plug-in depending on other Bundle interface packages for the Bundle project.
Export-Pacakges Bundle Export package (refer to OSGi’s concept of export package). The Quinox container loads classes from the corresponding Bundle, based on the export package. The property exportPackages must be set by the developer in the Bundle project. For example, a non-statically connected Bundle provides classes:com.alipay.android.phone.framework.api.ATo be used as an interface for other bundlescom.alipay.android.phone.framework.apiConfigure to export packages. The class used for reflection should also be included in the export package. Multiple exported packages are separated by ‘,’. For performance reasons, export packages should not be set too much or too wide.

4. Resource management

4.1 Resource Manager

As Android developers, we know through the Android. The content. res. The Resources object can get string, layout, graphics, animation, and other Resources.

The Quinox containerization framework does not allow you to manage multiple bundles, so instead of using Android’s native resource management logic, we built a Bundle resource manager that handles loading and calling resources from each Bundle.

However, since all bundles are compiled independently, the resources in them most likely have the same resource ID. Therefore, when there are the same resources, there may be conflicts, so how to resolve resource ID conflicts?

4.2 resource id

As Android programmers, we all know that the resource ID is an int that contains four bytes. It is generated by the AAPT tool when building an APK project and is defined in an R file.

Example code:

public final class R {
    public static final class drawable {
        public static int xxx_bg=0x1e020000;
    }
    public static final class id {
        public static int xxx_id=0x1e050001;
    }
    public static final class layout {
        public static int xxx_layout=0x1e030000;
    }
    public static final class string {
        public static int xxx_str=0x1e040001; }}Copy the code

These four bytes mean the following:

  • The first byte is pacakgeId.
  • The second byte is: typeId. It represents different resource types, such as strings, layouts, pictures, animations, etc.
  • The third and fourth bytes add up to the id of the resource name

As shown in the figure below:

By now, as many readers have figured out, the Quinox container framework’s solution to resource ID conflicts is to have mPaaS packaging plugins use the modified AAPT tool to specify a different packageId for each Bundle project and partition isolation. This ensures that resource ids are not duplicated between bundles. This is why you need to specify a packageId in a Bundle project.

5. A container

Quinox is not open source yet, so we won’t cover source code analysis in this section.

We’ve talked a lot about bundles, but at the heart of containerization is how to manage bundles. This brings us to the container manager, whose main job is to coordinate bundles and add, delete, modify, and check information.

After the application starts, our container manager reads the configuration information and generates information instances for each Bundle.

5.1 Adding and Deleting Container Managers

The Quinox container framework aims to address the two core issues of modularity and dynamism of Android client apps. The adding and deleting capabilities are mostly used to realize dynamic capabilities, facilitating the container to dynamically add and delete bundles. Since this article focuses on the modularization capability, we will devote a separate topic to analyzing the dynamic capability of containers later in this part.

5.2 Container Manager: changed

As far as container managers are concerned, Quinox is mainly a container manager that can take advantage of this to optimize startup performance and adapt models. There are a lot of source code involved here, so we won’t go into too much analysis.

5.3 Container Manager: Check

The most frequently used functional interface for the container manager is the query interface:

  • Query against BundleName (remember the require-bundle property of the Bundle?)
  • Query by packageId (Bundle not 27)
  • Query based on the Android Component class Name (remember the Bundle component-name property?).

Through the query interface of the manager, we carry out coordination and communication among various bundles to complete the containerization function.

5.4 Starting a Component

In addition to the container manager, another important point is the initiator of the component. A Quinox container customizes the startup process for a native Android Activity to manage Activity creation and life cycle itself.

At the same time, since the Activity is created by our own initiator, we can also make some customized modifications to the Activity, so that it can better adapt to the container system. For example, we can assign our own resource manager to the Activity, manage the Activity stack and provide interfaces to the Activity, do some aspects of the Activity lifecycle, and so on.

Another benefit of custom component initiators is that they allow activities to run dynamically. Dynamic running refers to running activities that are not registered in the Manifest at the factory. This function is more about the ability to support the dynamic of the container.

Because the implementation logic of Activity dynamic operation involves more core technology points, we do not analyze the specific implementation for the time being.

6. Summary

Through this section, we have preliminarily understood the design idea and corresponding modules of mPaaS container framework in Android. Due to space constraints, we cannot cover many technical points.

Welcome to experience mPaaS. We also look forward to your feedback on the design ideas and specific practices of android-based container framework. Welcome to discuss and communicate with you.

Past reading

The opening | modular and decoupling type development in ant gold mPaaS theorypractice probing depth,

Dependency Analysis Guide between Bundles of Koubei App

The source code analysis | ant gold suit mPaaS RPC calls under the framework of course”

“Practice of Alipay Mobile Terminal Dynamic Solution”

Follow our public account, get first-hand mPaaS technology practice dry goods