美文网首页
Android之WIFI-基础篇AsyncChannel分析

Android之WIFI-基础篇AsyncChannel分析

作者: 锄禾豆 | 来源:发表于2022-02-11 20:11 被阅读0次

简介

AsyncChannel 双Handler进程通信(同一进程或不同进程)。重点分析不同进程通信的原理

案例

WifiManager 客户端
WifiService 服务端

AsyncChannel属于联系两者的媒介

源码

7.1

补充点

Messenger

CountDownLatch

客户端:WifiManager

1.WifiManager 需要一个Handler ?
private class ServiceHandler extends Handler {
    ······
    public void handleMessage(Message message) {
         
    }
    ······
}

2.AsyncChannel与Handler建立连接?
    private synchronized AsyncChannel getChannel() {
        if (mAsyncChannel == null) {
            /**
            *    public Messenger getWifiServiceMessenger() {
            *        try {
            *            return mService.getWifiServiceMessenger();
            *        } catch (RemoteException e) {
            *            throw e.rethrowFromSystemServer();
            *        }
            *    }
            */
            Messenger messenger = getWifiServiceMessenger();//获取的是目的地的Messenger。即服务端的Handler
            mAsyncChannel = new AsyncChannel();
            Handler handler = new ServiceHandler(mLooper);//客户端的Handler
            mAsyncChannel.connect(mContext, handler, messenger);//将客户端和服务端的Handler建立连接
        }
        return mAsyncChannel;
    }

3.怎么知道连接成功?
流程:
1)AsynChannel通知WifiManager.ServiceHandler:CMD_CHANNEL_HALF_CONNECTED
2)WifiManager.ServiceHandler再通过AsynChannel告知服务端

a.查看AsyncChannel的api 
void connect(Context srcContext, Handler srcHandler, Messenger dstMessenger)

AsyncChannel.java
    public void connect(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
        if (DBG) log("connect srcHandler to the dstMessenger  E");

        // We are connected
        connected(srcContext, srcHandler, dstMessenger);

        // Tell source we are half connected
        replyHalfConnected(STATUS_SUCCESSFUL);

        if (DBG) log("connect srcHandler to the dstMessenger X");
    }
    
    片段1:connected
    public void connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
        if (DBG) log("connected srcHandler to the dstMessenger  E");

        // Initialize source fields
        mSrcContext = srcContext;
        mSrcHandler = srcHandler;
        mSrcMessenger = new Messenger(mSrcHandler);

        // Initialize destination fields
        mDstMessenger = dstMessenger;
        linkToDeathMonitor();//怎么知道服务端的对象不存在呢?linkToDeathMonitor就是监听的方法
        if (DBG) log("connected srcHandler to the dstMessenger X");
    }
    
    片段2:replyHalfConnected
    private void replyHalfConnected(int status) {
        Message msg = mSrcHandler.obtainMessage(CMD_CHANNEL_HALF_CONNECTED);
        msg.arg1 = status;
        msg.obj = this;
        msg.replyTo = mDstMessenger;
        if (!linkToDeathMonitor()) {
            // Override status to indicate failure
            msg.arg1 = STATUS_BINDING_UNSUCCESSFUL;
        }

        mSrcHandler.sendMessage(msg);//AsyncChannel发消息给客户端Handler,并带上服务端Handler(msg.replyTo = mDstMessenger)
    }
    
b.WifiManager.ServiceHandler通过AsynChannel告知服务端:CMD_CHANNEL_FULL_CONNECTION
    private void dispatchMessageToListeners(Message message) {
        ······
        switch (message.what) {
            case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
                if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
                    mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
                }
        ······
    }
    
    查看AsyncChannel的api
    void sendMessage(int what)
    
    public void sendMessage(int what) {
        Message msg = Message.obtain();
        msg.what = what;
        sendMessage(msg);
    }
    
    public void sendMessage(Message msg) {
        msg.replyTo = mSrcMessenger;
        try {
            mDstMessenger.send(msg);//服务端的Handler发送数据
        } catch (RemoteException e) {
            replyDisconnected(STATUS_SEND_UNSUCCESSFUL);
        }
    }
    
4.小结
AsyncChanel处理Handler跨进程通信的细节
1)AsyncChannel对象包含两个变量:mSrcMessenger、mDstMessenger
2)消息分发:
a.客户端处理CMD_CHANNEL_HALF_CONNECTED
b.服务端处理CMD_CHANNEL_FULL_CONNECTION

服务端WifiService(实现类:WifiServiceImpl)

1.WifiServiceImpl 需要一个Handler ?
private class ClientHandler extends Handler {
    ······
    public void handleMessage(Message message) {
         
    }
    ······
}

2.AsyncChannel与Handler建立连接?
    public Messenger getWifiServiceMessenger() {
        enforceAccessPermission();
        enforceChangePermission();
        return new Messenger(mClientHandler);
    }

3.服务端接收到CMD_CHANNEL_FULL_CONNECTION怎么处理?
    private class ClientHandler extends Handler {
        
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
                        if (DBG) Slog.d(TAG, "New client listening to asynchronous messages");
                        // We track the clients by the Messenger
                        // since it is expected to be always available
                        mTrafficPoller.addClient(msg.replyTo);
                    } else {
                        Slog.e(TAG, "Client connection failure, error=" + msg.arg1);
                    }
                    break;
                }
                ····
                case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
                    AsyncChannel ac = new AsyncChannel();
                    ac.connect(mContext, this, msg.replyTo);//服务端重新创建了一个AsyncChannel对象,将客户端的handler放在mTrafficPoller中
                    break;
                }
                ···
            }
        }
    }

总结

1.AsyncChannel处理双Handler进程间通信,核心在于Messenger承载了Handler
2.客户端和服务端,各自拿了一个AsyncChannel对象,通过connect建立连接

其他

AsyncChannel仍有很多其他好玩的API,例如:

public void connect(AsyncService srcAsyncService, Messenger dstMessenger)
AsyncService继承Service,封装中包裹一个Handler

public void connect(Context srcContext, Handler srcHandler, String dstPackageName,
            String dstClassName)
dstClassName是一个Service,binder需要继承IMessenger.Stub

public Message sendMessageSynchronously(Message msg)
消息同步处理,即消息发送出去等服务端处理完成后才有结果。
涉及算法知识栈类:Stack

等等等等

知识点

Messenger
概述
Messenger implements Parcelable,可跨进程传递数据

接口分析
public final class Messenger implements Parcelable {
    private final IMessenger mTarget;
    
    public Messenger(Handler target) {//传入Handler的构造方法
        mTarget = target.getIMessenger();
    }
    
    ······
    
    public Messenger(IBinder target) {//传入IBinder的构造方法
        mTarget = IMessenger.Stub.asInterface(target);
    }
}

补充
Handler类自带Messenger变量
    android.os.Handler:
    final IMessenger getIMessenger() {
        synchronized (mQueue) {
            if (mMessenger != null) {
                return mMessenger;
            }
            mMessenger = new MessengerImpl();
            return mMessenger;
        }
    }


场景

1.如果远程的对象死了,怎么知道?
Binder有一种linkToDeath机制

mDstMessenger.getBinder().linkToDeath(mDeathMonitor, 0);

2.WifiManager在使用AsyncChannel时,对于connect的回调方法,怎么进行监听?
a.采用了一种很巧妙的方法
b.SparseArray mListenerMap = new SparseArray();
仅仅将int值传给服务端,服务端传过来,在列表中查找对应的监听对象

相关文章

网友评论

      本文标题:Android之WIFI-基础篇AsyncChannel分析

      本文链接:https://www.haomeiwen.com/subject/knwqkrtx.html