Author: Gong Jin, senior r&d director of Individual Push

Stability, ease of use, security, small and flexible are the elements of a good SDK. As an early entrant of the third-party push market in China, Qitui has been committed to providing efficient and stable push SDK for developers. After years of grinding and innovation, Getui has accumulated rich technical experience. This article will share the technical experience of the Push SDK from four perspectives of “small”, “stable”, “easy to use” and “safe”.

1 small

1.1 65535 limit

A good push SDK is primarily about the small flexibility of the package body. Why smaller inclusion? For business people, the small size of the package makes it easier for them to accept. For technical personnel, when they are developing products, they generally pursue “less code, full function”, which is from the code cleanliness of programmers. From the code level, it is mainly due to the “65535 limit” of the system.

At the code level, this is due to the “65535 limit” of the system. As shown in the figure above (left), our program ends up generating a DEX file consisting of the following parts: headers (headers), a series of IDS (list of identifiers), data (data areas), and link_data (data used in statically linked files). If you look closely at the figure above (right), it contains a method_IDs_SIZE field, whose main purpose is to define numbers. According to Google, uint is a 16-bit short with a maximum length of 65535. If you decomcompile the dex project, many smali files will be generated. If you look at the smali function calls (e.g. Invoke Direct {***} @bbb), you will find that the address of the call is actually calculated from the offset defined in unit. Therefore, the maximum number of function addresses can be 65535.

1.2 How to reduce the volume of inclusion

How to reduce the volume of inclusion can be considered from the following aspects:

(1) Self-development, not nesting: When developing SDK, it is not recommended that developers nest a series of frameworks in SDK, such as tripartite network framework, DB framework or task scheduling framework, etc. We encourage developers to choose the most core part of their own development.

(2) Code optimization: from the algorithm level, the number of lines of code can be appropriately reduced under the same effect; No initial assignment is required for variables that have default assignments; Select an appropriate string concatenation method. It is recommended to use The StringBuilder method to concatenate strings, which can reduce the memory consumption caused by frequent string modification and reduce the package volume.

(3) Pursue practicality and give up perfection: THE SDK package should pursue practicality and focus on improving the main functions, while other relatively minor parts can reduce time or energy input and give up perfectionism thinking.

(4) Code obfuscation: use code obfuscation to achieve a smaller volume of packages, and it is not easy to reverse.

1.3 Save electricity and flow

Saving electricity and traffic is another aspect of being small. As a good message push SDK, there should be strict limits on the flow and power, otherwise there will be hot phone, high power consumption reminder, traffic waste, built-in SDK APP is difficult to be launched and other problems. To address the above problems, we can reduce the battery and traffic consumption caused by SDK as much as possible through Lock killer, intelligent heartbeat, custom protocol, link merge, active on demand, etc.

(1) Lock killer: WiFiLock, WakeLock, etc. in the code force the APP to wake up, resulting in a large power consumption of the APP. Such locks should be minimized or not used without compromising functionality.

(2) Intelligent heartbeat: different heartbeat strategies should be selected according to different operators and network states, and the maximum boundary of heartbeat should be explored according to different application scenarios, so as to prolong the heartbeat cycle as far as possible and reduce the power consumption and network consumption.

(3) the custom protocol: market commonly used json, XML, or even PB agreement, has good compatibility with scalability, but also create a problem of space waste, custom protocol can make full use of space, accurate use of each byte and bit, simplify the encapsulation, bearing the largest amount of information, reduce the flow and energy waste.

(4) Link combination: When a device has multiple APP push links active at the same time, we will use link combination technology to merge the long-link links between apps using “Individual push SDK” to reduce the waste of traffic and electricity.

2 the steady

2.1 Stability of lifting

In practical applications, developers may encounter tricky problems such as ANR, OOM, Crash, memory leak and flash back. In order to build a good message push SDK, we need to minimize errors through continuous iteration and optimization.

(1) Good code management: In addition to using SVN, GIT and other tools to do a good job of code hosting, developers also need to follow certain code specifications, use gerrit and other tools to review code, use verify process. In the premise of ensuring that the machine can not find the problem, and then human eyes to identify whether the business logic.

(2) Automated testing: Automated testing can greatly improve the efficiency of regression testing, which is very suitable for the agile development process. In addition, automated testing can replace a lot of manual mechanical repetitive operations, and test engineers can spend more time on more comprehensive use case design and new function testing.

(3) the use of code modularization and other small skills: code modularization can meet more personalized needs more quickly with the least modules and parts. Exception handling can improve the fault tolerance of the system and make the program more stable. Code detection can timely find defects and errors in the program, such as detection of memory leaks, whether there are security loopholes, etc., to ensure the quality of code.

(4) Online gray scale: in the actual scene, it is difficult for us to cover all environments, such as models and networks, etc., so we need to verify the robustness of the code through the feedback of online users. Therefore, we need to do a small amount of real user testing, i.e. grayscale rollout, to help reduce the risk before we launch the product to users on a large scale.

(5) Log system: it is inevitable that the system has problems. On the premise of keeping the system stable as far as possible, fault tolerance should be considered. When problems occur, you need to rectify them as soon as possible, so you need to have a complete log system. In addition, we can also check the robustness of the log system through dial-up, so that problems can be found and solved in time before users give feedback.

2.2 compatibility

Compatibility is also an important condition to ensure the stability of a good message push SDK, mainly considering the following aspects:

(1) Interface compatibility: After each version update, the external interface should remain unchanged as far as possible. For interfaces that have changed a lot, you can use the @deprecated annotation to mark the old interface and make it compatible with the new interface call, rather than simply deleting the old interface.

(2) Compatibility with primary keys: When the primary keys are changed (for example, removing service and provider), some old Android systems will have component cache, and the runtime will directly inform the “class” cannot be found. It is recommended to keep the declaration in the AndroidManifest and implement the code null for the corresponding “class” to reduce the probability of crash.

(3) Compatibility of Android system: build.version.sdk_int can be used to distinguish API.

(4) Compatibility of real machine: compatibility test can be carried out by cloud testing and other platforms.

3 to use

The usability of the SDK can be considered in the following aspects:

(1) Easy access: Integrated Demo can run directly when accessing SDK, and access documents are clear and steps are simple. One-click integration is best.

(2) Maintain core advantages: for a good message push SDK, we mainly consider timeliness, arrival rate, stability and accuracy. For example, news media apps have high requirements on the timeliness of push; Notification push (such as transfer information) will pay special attention to the message arrival rate; Stability refers to ensuring the normal operation of push SDKS in different environments, especially in high concurrency scenarios such as 11.11. Accuracy is mainly aimed at advertising and marketing push, which needs to push the right content to the right people at the right time, the right place and the right scene. How to ensure stability can be considered from the perspectives of multiple lines, multiple IDCs, and hot backup. ① Multi-line adjustment: for example, embedded three-line domain name, do some polling strategy to prevent domain name hijacking. ② more IDC Settings: in addition to domain name hijacking, but also may encounter network attacks, physical damage. Multiple IDCs are configured to realize traffic diversion and reduce risks on the other hand. ③ Hot backup: backup when the system is in normal operation. Once the system has a problem, it can be quickly recovered.

(3) Diversified needs: through rich portrait labels, intelligent push of scenes can be carried out for users to meet diversified needs of users.

(4) Controllable strategy: We also provide additional functions such as silent time, push control quantity, SMS supplement and timing display to meet customers’ actual usage scenarios.

$4 security

We also need to pay attention to security during SDK development. Security not only represents the security of network data interaction and local data storage, but also involves SDK reinforcement, confusion, third-party security software audit, etc.

We will focus on SDK hardening. At present, most of the SDK of Android platform is written in Java language, which is easy to be decomcompiled. If the SDK is simply obfuscated, it is easy to pry into the internal implementation details, and there is also the possibility that the SDK can be repackaged, embedded malicious ads, and so on. Therefore, we need to harden the SDK to improve security.

As shown in the figure above, the SDK hardening is mainly at the Java level and so level. At Java level, SSR IR instruction conversion or Java2C processing can be carried out, and implementation details can be put into native; At the SO level, some flattening and false control can be done to confuse the code, and the reverse difficulty can also be increased by instruction replacement and instruction jump logic. It is also possible to harden the SDK with constant string encryption, which is currently a simple and practical way to do this.

To sum up, it is not difficult to develop a good message push SDK. What is difficult is how to make our SDK run stably in a complex environment, which requires us to have a clear understanding of the SDK architecture, and keep iterating and optimizing. I hope this article can provide some help for developers in practical operation. Getui will continue to polish its technology and innovate, and share with you the latest ideas and methods on push and other fields.