android studio AIDL的使用(五)Messager的使用

1.全部代码:

1.MainActivity

package com.kunminx.exampleaidlmukewang;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

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

import com.kunminx.exampleaidlmukewang.entity.Message;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "MainActivity";
    private Button mBtConect;
    private Button mBtDisconnect;
    private Button mBtIsConnected;

    private IConnectionService connectionServiceProxy;
    private IServiceManager serviceManagerProxy;
    private IMessageService messageServiceProxy;
    private Button mBtSendMessage;
    private Button mBtRegisterListener;
    private Button mBtUnregister;
    private Button mBtMessenger;

    //信使来进行通信
    private Messenger messengerProxy;

    private Handler handle=new Handler(Looper.getMainLooper()){
        @Override
        public void handleMessage(@NonNull android.os.Message msg) {
            super.handleMessage(msg);
            Bundle bundle = msg.getData();//获取数据
            bundle.setClassLoader(Message.class.getClassLoader());//注意,这句可以解决序列化问题
            final Message message = bundle.getParcelable("message");//key获取值
            handle.postDelayed(new Runnable() {//延迟执行
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this, "MainActivity打印了:"+message.getContent(), Toast.LENGTH_SHORT).show();
                }
            }, 1000);
        }
    };
    //接收子进程的消息
    private Messenger clientMessenger =new Messenger(handle);
    /**IPC
     * 对AIDL创建的类的方法的实现
     * remoteService对main方法的调用,相当于反向调用
     */
    private MessageReceiverListener messageReceiverListener=new MessageReceiverListener.Stub() {
        @Override
        public void onReceiveMessage(final Message message) throws RemoteException {
            new Handler(Looper.getMainLooper()).post(new Runnable() {//实现方法
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this, message.getContent(), Toast.LENGTH_SHORT).show();
                }
            });
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        Intent mIntent = new Intent(this, RemoteService.class);
        bindService(mIntent, 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()));
                    //信使代理初始化
                    messengerProxy=new Messenger(serviceManagerProxy.getService(Messenger.class.getSimpleName()));
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {

            }
        }, BIND_AUTO_CREATE);
    }

    private void initView() {
        mBtConect = (Button) findViewById(R.id.bt_conect);
        mBtDisconnect = (Button) findViewById(R.id.bt_disconnect);
        mBtIsConnected = (Button) findViewById(R.id.bt_isConnected);
        mBtSendMessage = (Button) findViewById(R.id.bt_send_message);
        mBtRegisterListener = (Button) findViewById(R.id.bt_register_listener);
        mBtUnregister = (Button) findViewById(R.id.bt_unregister);
        mBtConect.setOnClickListener(this);

        mBtMessenger = (Button) findViewById(R.id.bt_messenger);
        mBtMessenger.setOnClickListener(this);
        mBtDisconnect.setOnClickListener(this);
        mBtIsConnected.setOnClickListener(this);
        mBtSendMessage.setOnClickListener(this);
        mBtRegisterListener.setOnClickListener(this);
        mBtUnregister.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bt_conect:
                try {
                    connectionServiceProxy.connect();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
            case R.id.bt_disconnect:
                try {
                    connectionServiceProxy.disconnect();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
            case R.id.bt_isConnected:
                boolean isConnection = false;
                try {
                    isConnection = connectionServiceProxy.isConnection();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                Toast.makeText(this, String.valueOf(isConnection), Toast.LENGTH_SHORT).show();
                break;
            case R.id.bt_send_message:
                Message message=new Message();
                message.setContent("这个消息来自main");
                try {
                    messageServiceProxy.sendMessage(message);
                    Log.d(TAG, "onClick: "+String.valueOf(message.isSendSuccess()));
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
            case R.id.bt_register_listener:
                try {
                    messageServiceProxy.registerMessageReceiveListener(messageReceiverListener);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
            case R.id.bt_unregister:
                try {
                    messageServiceProxy.unRegisterMessageReceiveListener(messageReceiverListener);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
            case R.id.bt_messenger:
                try {
                    Message message1=new Message();//自定义的序列化消息
                    message1.setContent("hello! 我是来自Main,Messager乘车员");//消息内容
                    Bundle bundleData=new Bundle();//初始化Bundle
                    bundleData.putParcelable("message",message1);//Bundle可以传递序列化数据
                    android.os.Message mMessage=new android.os.Message();//初始化android.os.Message
                    mMessage.replyTo= clientMessenger;
                    mMessage.setData(bundleData);//android.os.Message的参数是Bundle
                    messengerProxy.send(mMessage);//这里是信使代理发送消息,参数是android.os.Message,不要搞错成message
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
        }
    }
}

2.RemoteService

package com.kunminx.exampleaidlmukewang;

import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Messenger;
import android.os.Parcelable;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;

import com.kunminx.exampleaidlmukewang.entity.Message;

import java.util.ArrayList;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class RemoteService extends Service {
    private static final String TAG = "RemoteService";
    private boolean isConnected = false;
    //用arrayList来储存消息的监听
    private RemoteCallbackList<MessageReceiverListener> messageReceiverListenerRemoteCallbackList = new RemoteCallbackList<>();
    private ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;
    //模拟消息接收的过程,通过定时任务
    private ScheduledFuture scheduledFuture;


    public RemoteService() {
    }


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

            Bundle bundle = msg.getData();
            bundle.setClassLoader(Message.class.getClassLoader());//注意,这句可以解决序列化问题
            Message message = bundle.getParcelable("message");
            Toast.makeText(RemoteService.this, "remoteServiceToast了:" + message.getContent(), Toast.LENGTH_SHORT).show();
            /**
             * 回复
             */
            try {
                Messenger clientMessenger = msg.replyTo;//初始化msg的消息回复,这个是消息回复用的,可以发回给MainActivity
                Message reply = new Message();
                reply.setContent("来之remoteService的回复");
                android.os.Message data = new android.os.Message();
                data.replyTo = clientMessenger;//令android.os.Message的replaceTo等于msg.replayTo
                bundle = new Bundle();
                bundle.putParcelable("message", reply);
                data.setData(bundle);
                clientMessenger.send(data);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    };
    //注意:下面这些都是运行在子线程中的,所有Toast要线程通信
    private Messenger messenger = new Messenger(handler);

    private IConnectionService connectionService = new IConnectionService.Stub() {
        @Override
        public void connect() throws RemoteException {
            try {
                Thread.sleep(5000);
                isConnected = true;
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(RemoteService.this, "connect", Toast.LENGTH_SHORT).show();
                    }
                });
                //单位:s
                scheduledFuture = scheduledThreadPoolExecutor.scheduleAtFixedRate(
                        new Runnable() {
                            @Override
                            public void run() {
                                //遍历消息接收的监听
                                int size = messageReceiverListenerRemoteCallbackList.beginBroadcast();
                                for (int i = 0; i < size; i++) {
                                    Message message = new Message();
                                    message.setContent("这个消息来自remoteService");
                                    try {
                                        messageReceiverListenerRemoteCallbackList.getBroadcastItem(i).onReceiveMessage(message);
                                    } catch (RemoteException e) {
                                        e.printStackTrace();
                                    }
                                }
                                messageReceiverListenerRemoteCallbackList.finishBroadcast();
                            }
                        }//执行的方法
                        , 5000//第一次执行的时间
                        , 5000//执行时间间隔
                        , TimeUnit.MILLISECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void disconnect() throws RemoteException {
            isConnected = false;

            handler.post(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(RemoteService.this, "idsconnect", Toast.LENGTH_SHORT).show();
                }
            });
            //断联后把定时任务停掉
            scheduledFuture.cancel(true);

        }

        @Override
        public boolean isConnection() throws RemoteException {
            return isConnected;
        }
    };
    //消息服务
    private IMessageService messageService = new IMessageService.Stub() {
        @Override
        public void sendMessage(final Message message) throws RemoteException {
            Log.d(TAG, "sendMessage: " + message.getContent());
            //打印消息内容
            handler.post(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(RemoteService.this, message.getContent(), Toast.LENGTH_SHORT).show();
                }
            });
            if (isConnected) {
                message.setSendSuccess(true);
            } else {
                message.setSendSuccess(false);
            }
        }

        @Override
        public void registerMessageReceiveListener(MessageReceiverListener messageReceiverListener) throws RemoteException {
            if (messageReceiverListener != null) {//如果消息监听不为空,就把它添加进来(注册)
                messageReceiverListenerRemoteCallbackList.register(messageReceiverListener);
            }
        }

        @Override
        public void unRegisterMessageReceiveListener(MessageReceiverListener messageReceiverListener) throws RemoteException {
            if (messageReceiverListener != null) {//取消注册
                messageReceiverListenerRemoteCallbackList.unregister(messageReceiverListener);
            }
        }
    };
    private IServiceManager 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 if (Messenger.class.getSimpleName().equals(serviceName)) {
                return messenger.getBinder();
            } else {
                return null;
            }
        }
    };

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

    @Override
    public void onCreate() {
        super.onCreate();
        scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);
        IConnectionService.Default aDefault = new IConnectionService.Default() {
            @Override
            public void connect() throws RemoteException {
                super.connect();
            }

            @Override
            public void disconnect() throws RemoteException {
                super.disconnect();
            }

            @Override
            public boolean isConnection() throws RemoteException {
                return super.isConnection();
            }

            @Override
            public IBinder asBinder() {
                return super.asBinder();
            }
        };
    }
}

3.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">


    <Button
        android:id="@+id/bt_conect"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="connect" />

    <Button
        android:id="@+id/bt_disconnect"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="disconnect" />

    <Button
        android:id="@+id/bt_isConnected"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="isConnected" />


    <Button
        android:id="@+id/bt_send_message"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="send" />

    <Button
        android:id="@+id/bt_register_listener"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="register" />

    <Button
        android:id="@+id/bt_unregister"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="unregister" />
    <Button
        android:id="@+id/bt_messenger"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="messenger" />
</LinearLayout>

4.Message

package com.kunminx.exampleaidlmukewang.entity;

import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable.Creator;

/**
 * @ClassName Message
 * @Description TODO
 * @Author ${孙伟豪}
 * @Date 2020/11/6 14:54
 * @Version 1.0
 */
public class Message implements Parcelable {//实现序列化,不然不行
    private String content;//发送的内容
    private boolean isSendSuccess;//发送的状态


    @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 Message() {
    }

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

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

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

    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;
    }
    //inout的时候添加
    public void readFromParcel(Parcel parcel){
        content=parcel.readString();
        isSendSuccess=parcel.readByte()==1;
    }
}

2.步骤:

1.初始化信使代理

在RemoteService初始化之后,MainActivity就可以获取到它

//注意:下面这些都是运行在子线程中的,所有Toast要线程通信
    private Messenger messenger = new Messenger(handler);

在这里插入图片描述

else if (Messenger.class.getSimpleName().equals(serviceName)) {
                return messenger.getBinder();
            }

2.在MainActivity(客户端)中获取Messager

在这里插入图片描述

//信使来进行通信
    private Messenger messengerProxy;
//信使代理初始化
                    messengerProxy=new Messenger(serviceManagerProxy.getService(Messenger.class.getSimpleName()));

3.在MainActivity中执行消息发送,发送到RemoteService

Message message1=new Message();//自定义的序列化消息
                    message1.setContent("hello! 我是来自Main,Messager乘车员");//消息内容
                    Bundle bundleData=new Bundle();//初始化Bundle
                    bundleData.putParcelable("message",message1);//Bundle可以传递序列化数据
                    android.os.Message mMessage=new android.os.Message();//初始化android.os.Message
                    mMessage.setData(bundleData);//android.os.Message的参数是Bundle
                    messengerProxy.send(mMessage);//这里是信使代理发送消息,参数是android.os.Message,不要搞错成message

4.在Remote中打印出来

因为相当于在子线程中执行的,所以要用在这里插入图片描述

Bundle bundle = msg.getData();
            bundle.setClassLoader(Message.class.getClassLoader());//注意,这句可以解决序列化问题
            Message message = bundle.getParcelable("message");
            Toast.makeText(RemoteService.this, "remoteServiceToast了:" + message.getContent(), Toast.LENGTH_SHORT).show();
在此,消息发送就成功了,下面是消息的回复,remoteService发送消息回MainActivity

图解:在这里插入图片描述

5.在RemoteService的Handle中执行消息发送

try {
                Messenger clientMessenger = msg.replyTo;//初始化msg的消息回复,这个是消息回复用的,可以发回给MainActivity
                Message reply = new Message();
                reply.setContent("来之remoteService的回复");
                android.os.Message data = new android.os.Message();
                data.replyTo = clientMessenger;//令android.os.Message的replaceTo等于msg.replayTo
                bundle = new Bundle();
                bundle.putParcelable("message", reply);
                data.setData(bundle);
                clientMessenger.send(data);
            } catch (RemoteException e) {
                e.printStackTrace();
            }

在这里插入图片描述

6.MainActivity接收消息,并Toast出来

在这里插入图片描述

Bundle bundle = msg.getData();//获取数据
            bundle.setClassLoader(Message.class.getClassLoader());//注意,这句可以解决序列化问题
            final Message message = bundle.getParcelable("message");//key获取值
            handle.postDelayed(new Runnable() {//延迟执行
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this, "MainActivity打印了:"+message.getContent(), Toast.LENGTH_SHORT).show();
                }
            }, 1000);

7.最后加上这一句与添加到Messenger中在这里插入图片描述

mMessage.replyTo=clientMessager;

把handle添加到Handle中

//接收子进程的消息
    private Messenger clientMessenger =new Messenger(handle);//参数,Handle

图解:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值