要實現IPC(跨進程通信),可以使用官方給我們提供的Messenger機制和AIDL機制。
其中Messenger使用簡單,適用於大部分多進程、單線程的應用,
AIDL適用於較爲複雜的多進程、多線程的應用。
這裏我們介紹Messenger的用法,其底層也是使用AIDL實現的。
來看下Messenger用法
Reference to a Handler, which others can use to send messages to it.
This allows for the implementation of message-based communication across
processes, by creating a Messenger pointing to a Handler in one process,
and handing that Messenger to another process.
Messenger需要傳遞一個Handler,用於處理跨進程消息
構造:Messenger(Handler target)
發送消息:send(Message message) throws RemoteException
傳遞給客戶端:可以通過IBinder機制 IBinder getBinder()
要使用這套機制,必須爲通信雙方建立各自的Messenger,然後Service的Messenger依然是通過IBinder傳遞到Activity,Activity也可以將自己的Messenger通過Message的replyTo屬性傳遞到Service。
注意:跨進程通信使用Bundle,否則會報錯Java.lang.RuntimeException: Can’t marshal non-Parcelable objects across processes.
雙向通訊例子:
客戶端給服務端發送消息,服務端接收到後對值進行累計
累計到10後,給客戶端發送消息,客戶端顯示升級
多進程服務聲明
<service
android:name=".Messenger.MessengerService"
android:process=":it"
android:enabled="true"
android:exported="true"
></service>
服務端
/*
* Copyright (c) 2020.
* author: duck
*/
package com.ducky.cachepicasso.Messenger;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
public class MessengerService extends Service {
static final String TAG = "Messenger-Service";
private int sum = 0;
public MessengerService() {
}
private Messenger messenger = new Messenger(new ServiceHandler());
private Messenger mClient;
public class ServiceHandler extends Handler{
private static final int SIG_GET_PLUS = 0;
private static final int SIG_SEND_UPDATE = 1;
@Override
public void handleMessage(@NonNull Message msg) {
// 處理消息
switch(msg.what){
case SIG_GET_PLUS:
Bundle bundle = msg.getData();
sum += bundle.getInt("value");
Toast.makeText(MessengerService.this, sum+"", Toast.LENGTH_SHORT).show();
// =10 給客戶端發送消息
mClient = msg.replyTo;
if (null == mClient) {
return;
}
if (sum == 10) {
Message message = Message.obtain(null, SIG_SEND_UPDATE);
try {
mClient.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
break;
default:
break;
}
}
}
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "service bind");
return messenger.getBinder();
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "service unbind");
return super.onUnbind(intent);
}
}
客戶端
/*
* Copyright (c) 2020.
* author: duck
*/
package com.ducky.cachepicasso.Messenger;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.ducky.cachepicasso.R;
public class MessengerActivity extends AppCompatActivity {
static final String TAG = "Messenger-Activity";
// 服務端的Messenger
private Messenger mService;
// 客戶端的Messenger
private Messenger mMessenger;
// 向服務端發送的信號
private static final int SIG_SEND_PLUS = 0;
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "service connected");
mService = new Messenger(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "service disconnected");
mService = null;
}
};
public class ClientHandler extends Handler{
// 從服務端接收的信號
private static final int SIG_GET_UPDATE = 1;
@Override
public void handleMessage(@NonNull Message msg) {
switch (msg.what){
case SIG_GET_UPDATE:
Toast.makeText(MessengerActivity.this, "升級!", Toast.LENGTH_SHORT).show();
break;
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_messenger);
// 客戶端Messenger
mMessenger = new Messenger(new ClientHandler());
// 綁定服務
bindService(new Intent(this, MessengerService.class), serviceConnection, Context.BIND_AUTO_CREATE);
// 點擊按鈕 向服務端發送一次消息 服務端去做+
// 當服務端累計值達到10時 給客戶端發送消息
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mService != null) {
try {
Message message = Message.obtain(null, SIG_SEND_PLUS);
Bundle bundle = new Bundle();
bundle.putInt("value", 1);
message.setData(bundle);
message.replyTo = mMessenger;
mService.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(serviceConnection);
}
}