一、結構
說明:
- 主程式有一個Service,負責維護監聽器列表,以及監聽相關事件,併傳送給子程式
- 子程式需要繫結主程式的Service,並註冊監聽
- 主程式和子程式內的事件通過EventBus傳送,需要跨程式的通過Binder轉發
二、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;
複製程式碼
三、本地客戶端
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);
}
}
複製程式碼
四、子程式
RemoteService:子程式,用來繫結主程式,並註冊監聽
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中配置service
<service android:name=".LocalService" >
<intent-filter>
<action android:name="localservice"/>
</intent-filter>
</service>
<service
android:name=".aidl.RemoteService"
android:process=":remote" />
複製程式碼
通過以上的程式碼,可以實現使用EventBus在主程式和子程式之間通訊。
五、多module
將主程式的service和子程式的service放到不同的module中:
base:基礎module,包含了aidl檔案和Msg實體類,以及LocalService
child:子程式,包含RemoteService,並在AndroidManifest.xml配置service的程式,需要在build.gradle中配置對base的依賴
app:主module,包含MainActivity,需要在build.gradle中配置對base和child的依賴
六、多APP通訊
將AIDL檔案和實體類拷貝到main目錄下,保證包名和路徑正確,即可實現app之間的通訊。
在第二個APP中,使用顯式的intent來繫結第一個APP中的LocalService,使用LocalService設定的action。