簡單跨進程使用EventBus

1、結構

說明:

  1. 主進程有一個Service,負責維護監聽器列表,以及監聽相關事件,併發送給子進程
  2. 子進程須要綁定主進程的Service,並註冊監聽
  3. 主進程和子進程內的事件經過EventBus發送,須要跨進程的經過Binder轉發

2、AIDL接口

工程結構:

定義AIDL接口:
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 {
    //子進程向主進程註冊事件回調
    void registerCallback(IRemoteCallback callback);
	//子進程解註冊
    void unregisterCallback(IRemoteCallback callback);
	//子進程向主進程通知事件
    void notify(in Msg msg);
}
複製代碼
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);
}
複製代碼
Msg.aidl:
// Msg.aidl
package com.example.autolog.aidl;
//消息類型
parcelable Msg;
複製代碼

3、本地客戶端

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

import android.os.Parcel;
import android.os.Parcelable;
//消息實體類,須要實現Parcelable接口,跨進程時須要進行序列化
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 new Msg[size];
        }
    };

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(code);
        dest.writeString(message);
    }

    @Override
    public int describeContents() {
        return 0;
    }
}
複製代碼
LocalService.java:主進程的Service,其餘進程須要綁定該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能夠進行監聽對象的移除
    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);
            //子進程發送事件後,用EventBus分發
            EventBus.getDefault().post(msg);
        }
    };

	//監聽EventBus發送的字符串事件,並調用子進程的監聽器
    @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() {
        super.onCreate();
        EventBus.getDefault().register(this);
    }

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

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
}
複製代碼
MainActivity.java:主頁面,此處用來啓動LocalService和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() {
                while (true) {
                    try {
                        Thread.sleep(3000);
                        //發送事件,由LocalService處理,並通知給子進程
                        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){
        //子進程事件發送到LocalService後,處理EventBus發送的事件
        Log.v("aidl-service", "main activity preocess code:"+msg.code+" msg:"+msg.message);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }
}
複製代碼

4、子進程

RemoteService:子進程,用來綁定主進程,並註冊監聽java

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() {
        super.onCreate();
        Log.v("aidl-service", "remoteservice oncreate " + getPackageName());
        Intent it = new Intent(this, LocalService.class);
        //綁定主進程的服務
        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 {
                    //註冊監聽
                    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() {
                            while (true) {
                                try {
                                    Thread.sleep(2000);
                                    //向主進程發送事件
                                    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;
    }
}
複製代碼

在AndroidManifest.xml中配置serviceandroid

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

<service android:name=".aidl.RemoteService" android:process=":remote" />
複製代碼

經過以上的代碼,能夠實現使用EventBus在主進程和子進程之間通訊。併發

5、多module

將主進程的service和子進程的service放到不一樣的module中:app

base:基礎module,包含了aidl文件和Msg實體類,以及LocalService

child:子進程,包含RemoteService,並在AndroidManifest.xml配置service的進程,須要在build.gradle中配置對base的依賴

app:主module,包含MainActivity,須要在build.gradle中配置對base和child的依賴

6、多APP通訊

將AIDL文件和實體類拷貝到main目錄下,保證包名和路徑正確,便可實現app之間的通訊。ide

在第二個APP中,使用顯式的intent來綁定第一個APP中的LocalService,使用LocalService設置的action。post

相關文章
相關標籤/搜索