Android IPC通信

Android IPC通信

概述

  • 进程时系统资源分配的最小单位;进程间的资源和数据相互隔离;进程内可以运行多个线程,线程的崩溃会影响到进程
  • 进程间通信指通过内核提供的机制完成数据交换,IPC(Inter Progress Communication)
  • Linux跨进程通信方式:管道、消息队列、信号、共享内存、信号量、套接字
  • Android跨进程通信方式
    • Binder:稳定性好,优于共享内存方式;性能好,数据拷贝次数优于管道、消息队列、socket;安全性高,UID/PID可见
    • AIDL:基于Binder机制,定义IPC过程中接口的一种描述语言,AIDL文件在编译过程中生成接口的实现类,用于IPC通信;支持基本数据类型,实现Parcelable接口的对象,List,Map
    • Messenger:基于Binder机制,只支持串行实时通信;只支持bundle传输的数据类型

AIDL

  • AIDL即Android Interface Definition Language,接口定义语言,定义IPC过程中一种描述语言

  • AIDL文件以.aidl为后缀名

  • AIDL支持数据类型:

    • 基本数据类型:byte、char、short、int、long、float、double、boolean
    • String、CharSequence
    • 实现Parcelable接口类型
    • List和Map类型
  • 定向Tag,定义数据的流向

    • in:数据只能由客户端向服务端
    • out:数据只能服务端向客户端
    • inout:客户端与服务端双向流向
  • oneway关键字:单向调用,不需要等待另一个进程的返回结果,不会产生阻塞问题,不能有返回值

  • 明确导包,在AIDL文件中需要明确导包定义的数据类型

  • 所有IPC调用的方法执行都是在binder线程里,可能需要切换主线程

代码结构

在这里插入图片描述

定义AIDL文件

aidl目录下新建以前文件

package com.example.myapplication;

//关联实体类
//消息类
parcelable Message;
package com.example.myapplication;

/**
* 连接状态服务
*/
interface IConnectionService {
    //建立连接
    oneway void connect();
    //断开连接
    void disconnect();
    //判断是否已连接
    boolean isConnected();
}
package com.example.myapplication;

//导包
import com.example.myapplication.Message;
import com.example.myapplication.MessageReceiveListener;

/**
* 发送消息服务
*/
interface IMessageService {
    //发送消息
    //实体类需要标记关键字in,基本类型不用
    void sendMessage(in Message message);

    //注册监听
    void registerMessageReceiveListener(MessageReceiveListener messageReceiveListener);

    //取消注册
    void unregisterMessageReceiveListener(MessageReceiveListener messageReceiveListener);
}
package com.example.myapplication;

//导包
import com.example.myapplication.Message;

/**
* 管理消息监听
*/
interface MessageReceiveListener {

    //接收消息
    void onReceiveMessage(in Message message);
}
package com.example.myapplication;

//管理类
interface IServiceManager {

    IBinder getService(String serviceName);
}

定义消息类

public class Message implements Parcelable {
    private String content;
    private boolean isSendSuccess;

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public boolean isSendSuccess() {
        return isSendSuccess;
    }

    public void setSendSuccess(boolean sendSuccess) {
        isSendSuccess = sendSuccess;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.content);
        dest.writeByte(this.isSendSuccess ? (byte) 1 : (byte) 0);
    }

    public void readFromParcel(Parcel source) {
        this.content = source.readString();
        this.isSendSuccess = source.readByte() != 0;
    }

    public Message() {
    }

    protected Message(Parcel in) {
        this.content = in.readString();
        this.isSendSuccess = in.readByte() != 0;
    }

    public static final Parcelable.Creator<Message> CREATOR = new Parcelable.Creator<Message>() {
        @Override
        public Message createFromParcel(Parcel source) {
            return new Message(source);
        }

        @Override
        public Message[] newArray(int size) {
            return new Message[size];
        }
    };
}

定义客户端代码

public class MainActivity extends AppCompatActivity {

    private IServiceManager serviceManagerProxy;

    private IConnectionService connectionServiceProxy;

    private IMessageService messageServiceProxy;

    private MessageReceiveListener.Stub messageReceiverListener = new MessageReceiveListener.Stub() {

        @Override
        public void onReceiveMessage(Message message) throws RemoteException {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    //接收服务端的消息
                    Utils.log(message.getContent());
                }
            });
        }
    };

    @Override
    protected void onCreate(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        Intent intent = new Intent(this, RemoteService.class);
        bindService(intent, new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                try {
                    serviceManagerProxy = IServiceManager.Stub.asInterface(service);

                    connectionServiceProxy = IConnectionService.Stub.asInterface(serviceManagerProxy.getService(IConnectionService.class.getSimpleName()));

                    messageServiceProxy = IMessageService.Stub.asInterface(serviceManagerProxy.getService(IMessageService.class.getSimpleName()));

                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {

            }
        }, Context.BIND_AUTO_CREATE);


        binding.connect.setOnClickListener(v -> {
            try {
                connectionServiceProxy.connect();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        });

        binding.disconnect.setOnClickListener(v -> {
            try {
                connectionServiceProxy.disconnect();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        });

        binding.isconnected.setOnClickListener(v -> {
            try {
                boolean isconnected = connectionServiceProxy.isConnected();
                Utils.toast(isconnected ? "连接成功" : "连接失败");
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        });

        binding.sendMessage.setOnClickListener(v -> {
            Message message = new Message();
            message.setContent("主进程发送消息-BBB");
            try {
                //向服务端发送消息
                messageServiceProxy.sendMessage(message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        });

        binding.register.setOnClickListener(v -> {
            try {
                messageServiceProxy.registerMessageReceiveListener(messageReceiverListener);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        });

        binding.unregister.setOnClickListener(v -> {
            try {
                messageServiceProxy.unregisterMessageReceiveListener(messageReceiverListener);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        });
    }
}

定义服务端代码

public class RemoteService extends Service {

    private Handler handler = new Handler(Looper.getMainLooper());

    private boolean isConnected = false;

    private RemoteCallbackList<MessageReceiveListener> receiverList = new RemoteCallbackList<>();

    private ScheduledThreadPoolExecutor mScheduledThreadPoolExecutor;

    private ScheduledFuture mScheduledFuture;

    private IConnectionService.Stub connectionService = new IConnectionService.Stub() {
        @Override
        public void connect() throws RemoteException {
            handler.post(() -> Utils.toast("开始连接,等待5s"));
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            handler.post(() -> Utils.toast("连接成功"));
            isConnected = true;

            mScheduledFuture = mScheduledThreadPoolExecutor.scheduleAtFixedRate(new Runnable() {
                @Override
                public void run() {
                    int size = receiverList.beginBroadcast();
                    for (int i = 0; i < size; i++) {
                        Message message = new Message();
                        message.setContent("子进程发送消息-AAA");
                        try {
                            //向客户端发送消息
                            receiverList.getBroadcastItem(i).onReceiveMessage(message);
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    }
                    receiverList.finishBroadcast();
                }
            }, 5000, 5000, TimeUnit.MILLISECONDS);
        }

        @Override
        public void disconnect() throws RemoteException {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    Utils.toast("断开连接");
                }
            });

            isConnected = false;
            mScheduledFuture.cancel(true);
        }

        @Override
        public boolean isConnected() throws RemoteException {
            return isConnected;
        }
    };


    private IMessageService.Stub messageService = new IMessageService.Stub() {
        @Override
        public void sendMessage(Message message) throws RemoteException {
            //接收客户端的消息
            handler.post(() -> Utils.toast(message.getContent()));
            message.setSendSuccess(isConnected);
        }

        @Override
        public void registerMessageReceiveListener(MessageReceiveListener messageReceiveListener) throws RemoteException {
            receiverList.register(messageReceiveListener);
        }

        @Override
        public void unregisterMessageReceiveListener(MessageReceiveListener messageReceiveListener) throws RemoteException {
            receiverList.unregister(messageReceiveListener);
        }
    };


    private IServiceManager.Stub serviceManager = new IServiceManager.Stub() {

        @Override
        public IBinder getService(String serviceName) throws RemoteException {
            if (IConnectionService.class.getSimpleName().equals(serviceName)) {
                return connectionService.asBinder();
            } else if (IMessageService.class.getSimpleName().equals(serviceName)) {
                return messageService.asBinder();
            } else {
                return null;
            }
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        mScheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return serviceManager.asBinder();
    }
}

AndroidManifest.xml文件注册

<service
         android:name=".RemoteService"
         android:enabled="true"
         android:exported="true"
         android:process=":remote1"></service>

Messenger

  • Messenger相比AIDL则简单很多
  • Messenger需要借助Handler&Message进行通信

获取Messenger对象

sendMessenger = new Messenger(serviceManagerProxy.getService(Messenger.class.getSimpleName()));

定义客户端代码

Messenger向服务端发送消息

Message message = new Message();
message.setContent("messenger发送了一个消息");
android.os.Message data = android.os.Message.obtain();
data.replyTo = receiveMessenger;//设置用于接收消息的Messenger
Bundle bundle = new Bundle();
bundle.putParcelable("message", message);
data.setData(bundle);
sendMessenger.send(data);

定义服务端

private Handler handler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(@NonNull android.os.Message msg) {
        super.handleMessage(msg);
        receive(msg);
        send(msg);
    }

    //接收客户端的消息
    private void receive(@NotNull android.os.Message msg) {
        Bundle data = msg.getData();
        data.setClassLoader(Message.class.getClassLoader());//防止序列化问题
        Message message = data.getParcelable("message");
        Utils.toast(message.getContent());
    }

    //向客户端回复消息
    private void send(@NonNull android.os.Message msg) {
        try {
            Message message = new Message();
            message.setContent("Messenger回复一个消息");

            android.os.Message data = android.os.Message.obtain();
            Bundle bundle = new Bundle();
            bundle.putParcelable("message", message);
            data.setData(bundle);

            Messenger m = msg.replyTo;
            m.send(data);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
};

private Messenger messenger = new Messenger(handler);

代码下载

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值