A, structure,

Description:

  1. The main process has a Service that maintains the list of listeners and listens for related events and sends them to the child process
  2. The child needs to bind the main process’s Service and register a listener
  3. Events within the main process and child processes are sent via EventBus and are forwarded by Binder across processes

Second, AIDL interface

Engineering structure:

Define the AIDL interface:
IEventInterface. Aidl:
// IEventInterface.aidl package com.example.autolog.aidl; import com.example.autolog.aidl.IRemoteCallback; // Declare any non-default types here with import statements import com.example.autolog.aidl.Msg; Interface IEventInterface {// The child registers the event callback with the main process void registerCallback(IRemoteCallback callback); Void unregisterCallback(IRemoteCallback callback); // The child notifies the main process of the event void notify(in Msg Msg); }Copy the code
IRemoteCallback. Aidl:
// IRemoteCallback.aidl package com.example.autolog.aidl; // Declare any non-default types here with import statements import com.example.autolog.aidl.Msg; Interface IRemoteCallback {// Void notifyEvent(in Msg Msg); }Copy the code
Msg. Aidl:
// Msg.aidl package com.example.autolog.aidl; // Message type parcelable Msg;Copy the code

Local client

Msg. Java:
package com.example.autolog.aidl;

import android.os.Parcel;
import android.os.Parcelable;
// Message entity class that needs to implement the Parcelable interface and needs to be serialized across processes
public class Msg implements Parcelable {
    public int code;
    public String message;

    public Msg(int code, String msg) {
        this.code = code;
        this.message = msg;
    }

    public Msg(Parcel in) {
        this.code = in.readInt();
        this.message = in.readString();
    }

    public final static Creator<Msg> CREATOR = new Creator<Msg>() {
        @Override
        public Msg createFromParcel(Parcel in) {
            return new Msg(in);
        }

        @Override
        public Msg[] newArray(int size) {
            return newMsg[size]; }};@Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(code);
        dest.writeString(message);
    }

    @Override
    public int describeContents(a) {
        return 0; }}Copy the code
Localservice. Java: Service of the main process. Other processes must bind to this Service
package com.example.autolog.aidl;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;

import androidx.annotation.Nullable;

import java.util.ArrayList;
import java.util.List;

import de.greenrobot.event.EventBus;
import de.greenrobot.event.Subscribe;

public class LocalService extends Service {
    RemoteCallbackList can be used to remove listener objects
    final RemoteCallbackList<IRemoteCallback> lis = new RemoteCallbackList<>();
    Binder mBinder = new IEventInterface.Stub() {
        @Override
        public void registerCallback(IRemoteCallback callback) throws RemoteException {
            Log.v("aidl-service"."localservice registercallback:" + callback + callback.asBinder());
            lis.register(callback);
        }

        @Override
        public void unregisterCallback(IRemoteCallback callback) throws RemoteException {
            Log.v("aidl-service"."localservice unregistercallback " + callback + callback.asBinder());
            lis.unregister(callback);
        }

        @Override
        public void notify(Msg msg) throws RemoteException {
            Log.v("aidl-service"."localservice notify code:" + msg.code + " message:" + msg.message);
            // The child process sends the event and distributes it using EventBusEventBus.getDefault().post(msg); }};// Listen for string events sent by EventBus and call the child's listener
    @Subscribe
    public void handle(String message) {
        Log.v("aidl-service"."localservice handle:" + message);
        synchronized (lis) {
            int n = lis.beginBroadcast();
            try {
                for (int i = 0; i < n; i++) {
                    lis.getBroadcastItem(i).notifyEvent(new Msg(0, message)); }}catch(RemoteException e) { e.printStackTrace(); } lis.finishBroadcast(); }}@Override
    public void onCreate(a) {
        super.onCreate();
        EventBus.getDefault().register(this);
    }

    @Override
    public void onDestroy(a) {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        returnmBinder; }}Copy the code
Mainactivity. Java: home page, used to launch LocalService and RemoteService
package com.example.autolog;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.example.autolog.aidl.Msg;
import com.example.autolog.aidl.RemoteService;
import com.example.autolog.aidl.LocalService;

import de.greenrobot.event.EventBus;
import de.greenrobot.event.Subscribe;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        startService(new Intent(this, LocalService.class));

        startService(new Intent(this, RemoteService.class));

        new Thread(new Runnable() {
            @Override
            public void run(a) {
                while (true) {
                    try {
                        Thread.sleep(3000);
                        // Sends an event, handled by LocalService, and notified to the child process
                        EventBus.getDefault().post("wahaha, i'am mainactivity:" + System.currentTimeMillis());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        EventBus.getDefault().register(this);
    }

    @Subscribe
    public void process(Msg msg){
        // The child processes the event sent by EventBus after the event is sent to LocalService
        Log.v("aidl-service"."main activity preocess code:"+msg.code+" msg:"+msg.message);
    }

    @Override
    protected void onDestroy(a) {
        super.onDestroy();
        EventBus.getDefault().unregister(this); }}Copy the code

Fourth, child process

RemoteService: child process used to bind the main process and register listeners

package com.example.autolog.aidl;

import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import androidx.annotation.Nullable;

import com.example.autolog.LocalService;
import com.example.autolog.aidl.IEventInterface;
import com.example.autolog.aidl.IRemoteCallback;
import com.example.autolog.aidl.Msg;

import de.greenrobot.event.EventBus;

public class RemoteService extends Service {
    IEventInterface iEventInterface;

    @Override
    public void onCreate(a) {
        super.onCreate();
        Log.v("aidl-service"."remoteservice oncreate " + getPackageName());
        Intent it = new Intent(this, LocalService.class);
        // Bind the services of the main process
        boolean r = bindService(it, new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.v("aidl-service"."remoteservice onserviceconnected");
                iEventInterface = IEventInterface.Stub.asInterface(service);
                try {
                    // Register listener
                    iEventInterface.registerCallback(new IRemoteCallback.Stub() {
                        @Override
                        public void notifyEvent(Msg msg) throws RemoteException {
                            Log.v("aidl-service"."remoteservice notifyevent code:" + msg.code + " message:"+ msg.message); EventBus.getDefault().post(msg); }});new Thread(new Runnable() {
                        @Override
                        public void run(a) {
                            while (true) {
                                try {
                                    Thread.sleep(2000);
                                    // Sends events to the main process
                                    iEventInterface.notify(new Msg(1."hello i'am remoteservice:" + System.currentTimeMillis()));
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }).start();
                } catch(RemoteException e) { e.printStackTrace(); }}@Override
            public void onServiceDisconnected(ComponentName name) {

            }
        }, BIND_AUTO_CREATE);
        Log.e("aidl-service"."remoteservice bind localservice " + r);
    }


    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null; }}Copy the code

Configure the service in androidmanifest.xml

<service android:name=".LocalService" >
   <intent-filter>
         <action android:name="localservice"/>
   </intent-filter>
</service>

<service
    android:name=".aidl.RemoteService"
    android:process=":remote" />
Copy the code

With the above code, you can use EventBus to communicate between the main process and child process.

More than five, the module

Put the service of the main process and the service of the child process into different modules:

Base: Base Module, which contains the AIDL file and Msg entity class, as well as LocalService

Child: a process that contains RemoteService and configates the service in androidmanifest.xml. The base dependency needs to be configured in build.gradle

App: Main Module, containing MainActivity, needs to configure base and Child dependencies in build.gradle

6. Multi-app communication

Copy the AIDL file and entity class to the main directory and ensure that the package name and path are correct to realize the communication between apps.

In the second APP, the LocalService in the first APP is bound with an explicit intent, using the action set by LocalService.