[![xipc][xipcsvg]][xipc] [![api][apisvg]][api]

An Android common IPC framework. The project is a self-understanding adaptation of the design of Hermes, an open source project of Ele. me.

About me

Characteristics of the

  • Support for custom service interface implementation process communication, no need to define AIDL interface, all IPC communication as simple as calling local functions.

  • Support for customizing interface services (service discovery), getting singletons, and getting tool class methods.

  • Interface callbacks that support process communication.

  • Thread control that supports interface callbacks.

  • Has a garbage collection mechanism to prevent interface callback memory leaks.

  • Supports cross-process and cross-application communication.

Realize the principle of

The framework is mainly implemented using the following technologies:

  • Annotations reflection

  • A dynamic proxy

  • AIDL

  • Service binding

  • Interprocess garbage collection

Please click to view the detailed implementation principle

Demo (star support)

Apk download

How to use

1. Add build.gradle repositories in the project root directory:

allprojects {
     repositories {
        maven { url "https://jitpack.io" }
Copy the code

2. Add to dependencies:

dependencies { ... Implementation 'com. Making. Xuexiangjys: XIPC: 1.0.1'}Copy the code

3. Register the interface service with Application:

XIPC.init(this); XIPC.debug(BuildConfig.DEBUG); Xipc.register (userManager.class); XIPC.register(LoadingTask.class); XIPC.register(FileUtils.class); XIPC.register(LoadingCallback.class); XIPC.register(ComputeService.class); Remote registered interface / / / / all of the package name defines the service interface XIPC. Register (com. Xuexiang. Remotedemo. "service");Copy the code

How to communicate across applications

1. Interface definition and implementation

(1) First, we need to define a unified set of interactive interfaces. Use @className and @methodName to decorate.

@classname ("ComputeService") public interface IComputeService {/** ** calculate * @param value1 value1 * @param symbol * @param value2 value2 * @return */ @methodname ("calculate") float calculate(float value1, String symbol, float value2); }Copy the code

(2) According to the defined interface, specific implementation. Use @className and @methodName to decorate. It is important to note that the content in the annotations corresponds to the interface defined previously.

public class ComputeService implements IComputeService {
    public float calculate(float value1, String symbol, float value2) {
        float result;
        switch(symbol) {
            case "+":
                result = value1 + value2;
            case "-":
                result = value1 - value2;
            case "*":
                result = value1 * value2;
            case "/":
                result = value1 / value2;
                result = value1 + value2;
        return result;
Copy the code

2. Registered

(1) Register the interface and implementation class. For calling App, you only need to register the interface; For the called App, only the implementation class and callback interface need to be registered. Registration is performed in onCreate of the Application.

Xipc.register (userManager.class); XIPC.register(LoadingTask.class); XIPC.register(FileUtils.class); XIPC.register(LoadingCallback.class); XIPC.register(ComputeService.class); / / call App, only need to register interface and the callback function XIPC. Register (" com. Xuexiang. Remotedemo. Service "); // This method registers all defined service interfaces under the package nameCopy the code

(2) The App to be invoked must register IPC communication service in manifest. You can use the default IPCService0 service or inherit IPCService to customize the communication service.

    android:exported="true" />
Copy the code

3. Service binding

(1) Before calling, please bind IPC communication service.

XIPC.connectApp(getContext(), "com.xuexiang.xipcdemo"); // The package name of the called App is set hereCopy the code

(2) Of course you can also set the listener callback of the binding to determine whether the service binding is successful.

XIPC.setIPCListener(new IPCListener() { @Override public void onIPCConnected(Class<? Extends IPCService> service) {toastutils.toast ("IPC service is bound!" ); }});Copy the code

4. Obtain instance access

XIPC provides three ways to access:

  • GetService: creates a service interface to obtain a general definition.

  • GetInstance: obtains a singleton.

  • GetUtilityClass: Gets the utility class.

IComputeService computeService = XIPC.getService(IComputeService.class);
ToastUtils.toast("3*4=" + computeService.calculate(3 , "*", 4));
Copy the code

5. Unbind services

When service access is no longer needed, we need to unbind services and reclaim resources in a timely manner.

Copy the code

Matters needing attention

In terms of interface registration

  • If two processes belong to two different apps (called App A and App B respectively). If App A wants to access A class of App B, and App A’s interface has the same package name and ClassName as App B’s corresponding implementation class, there is no need to annotate the class and interface with @classname. However, use ProGuard to keep the class name and package name the same.

  • If the interface and the corresponding method in the class have the same name, there is no need to annotate the method with @methodname. Also note that after ProGuard is used, the MethodName in the interface must still be the same as the corresponding MethodName in the class.

  • If either interface or implementation class uses the @className and @methodName decorations, the other must also use the same @className and @methodName decorations, otherwise an error will be reported.

  • Suppose process B needs to access process A. If process A uses A class identified by the @className annotation, then process B needs to apply the same @className annotation to its corresponding interface, and process A must register before process B can access the interface. Otherwise, XIPC cannot find A matching class in process A when process B uses xipc.getService (), xipc.getInstance (), or xipc.getutilityClass () to access process A.

  • All registered interface classes cannot be anonymous and local classes.

In order to avoid all sorts of mismatches and missing methodNames, it’s best to use the @className and @methodName annotations and register them in the Application’s onCreate.

In terms of interface definition

  • If you don’t want a class or function to be accessed by other processes, you can add the @WithinProcess annotation to it.

  • When using XIPC to call a function across a process, the type of the argument passed in can be a subclass of the original argument type. Be sure not to be an anonymous class or a local class, except for callback functions.

  • In terms of interface parameters, if the parameter type and return value type of the interface function to be called are basic types such as int and double or Java common types such as String and Object, no unnecessary operations are required. Note, however, that arrays are not currently supported. If you need an array as an argument, you can wrap the array with a custom object and then use it.

  • If the interface parameter type is a custom class, and the two processes belong to two different apps, you must define the class in both apps and ensure that if the code is confused, the two classes still have the same package name and class name. However, you can apply the @classname and @methodname annotations so that the package name and ClassName don’t get confused.

  • If the function being called has a callback argument, the argument in the function definition must be an interface, not an abstract class.

In terms of interface callbacks

  • Special attention needs to be paid to the thread in which the callback function runs. If process A calls process B’s function and passes in A callback function for process B to call back from process A, then by default the callback will run on process A’s main thread (UI thread). If you don’t want callback functions to run on the main thread, annotate @background before the corresponding callback argument of the function declared by the interface.

  • If the callback function returns a value, use the @background annotation to run it in the Background thread. If running on the main thread, the return value is always null.

  • In terms of references to callback functions, the framework holds strong references to callback functions, which can lead to memory leaks. To solve this problem, you can add @WeakRef annotations to the corresponding callback parameters of the interface declaration so that the XIPC holds a weak reference to the callback function. If a process’s callback function is reclaimed and the other process is still calling it (the other process does not know that the callback function was reclaimed), this has no effect and will not cause a crash. If the callback function returns a value, null is returned.

  • @background and @WeakRef annotations must be added in front of corresponding function parameters in the interface. If you add it anywhere else, it won’t do anything.

Other aspects

  • When a function is called, any Context in another process becomes its application Context.

  • Data passing for interface parameters is jSON-based by default.

  • If any error occurs during the debugging process, relevant logs will be recorded. You only need to run xipc. debug to enable debugging to view the logs.

Confuse configuration

# xipc -keep @com.xuexiang.xipc.annotation.* class * {*; } -keep class * { @com.xuexiang.xipc.annotation.* <fields>; } -keepclassmembers class * { @com.xuexiang.xipc.annotation.* <methods>; }Copy the code

Special thanks to


Wechat official account

More information, welcome to wechat search public number: [My Android open source journey]

[xipcsvg]: Img. Shields. IO/badge/XIPC -… [xipc]: Github.com/xuexiangjys… [apisvg]: Img. Shields. IO/badge/API – 1… [api]: Android-arsenal.com/api?level=1…