Messenger实现服务端和客户端之间的双向通信

Messenger支持双向通信。要实现双向通信,服务端和客户端都需要各自拥有一个Messenger实例(即一个Handler的封装),并通过Message对象交换彼此的Messenger引用。

服务端向客户端发送消息

  1. 客户端在发送消息给服务时,可以在Message对象中包含一个指向客户端Messenger的引用(通过Message.replyTo字段)。
  2. 服务接收到消息后,可以使用这个引用回复消息给客户端。

服务端(Service)

首先,更新服务端代码以允许服务接收客户端的Messenger并通过它发送消息回客户端。

java 复制代码
javaCopy Code
import android.app.Service;
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;

public class ExampleService extends Service {
    static final int MSG_SAY_HELLO = 1;
    static final int MSG_REGISTER_CLIENT = 2;
    static final int MSG_UNREGISTER_CLIENT = 3;
    static final int MSG_REPLY_TO_CLIENT = 4;

    Messenger mClient = null; // 用于保存客户端的Messenger,客户端注册完成后,可在服务端Handler回调中通过msg.replyTo获取对象
    //服务接收到消息后,可以使用这个引用回复消息给客户端。
    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_SAY_HELLO:
                    // 当服务收到来自客户端的问候时
                    sendMessageToClient(MSG_REPLY_TO_CLIENT, "Hello from Service!");
                    break;
                case MSG_REGISTER_CLIENT:
                    // 客户端注册自己的Messenger
                    mClient = msg.replyTo;
                    break;
                case MSG_UNREGISTER_CLIENT:
                    // 客户端取消注册其Messenger
                    mClient = null;
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    final Messenger mMessenger = new Messenger(new IncomingHandler());

    @Override
    public IBinder onBind(Intent intent) {
        return mMessenger.getBinder();
    }

    private void sendMessageToClient(int what, String text) {
        if (mClient != null) {
            try {
                Bundle bundle = new Bundle();
                bundle.putString("reply", text);
                Message msg = Message.obtain(null, what);
                msg.setData(bundle);
                mClient.send(msg);
            } catch (RemoteException e) {
                mClient = null; // 客户端已断开连接
            }
        }
    }
}

客户端(Activity)

接下来,更新客户端代码以注册其Messenger至服务,并处理服务的回复消息。

java 复制代码
javaCopy Code
import android.app.Activity;
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.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity {
    Messenger mService = null;
    boolean mBound = false;

    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case ExampleService.MSG_REPLY_TO_CLIENT:
                    String reply = msg.getData().getString("reply");
                    Toast.makeText(MainActivity.this, reply, Toast.LENGTH_SHORT).show();
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    final Messenger mMessenger = new Messenger(new IncomingHandler());
    /**
    客户端在发送消息给服务时,可以在`Message`对象中包含一个指向客户端`Messenger`的引用(通过    `Message.replyTo`字段)
    */
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            mService = new Messenger(service);
            mBound = true;
            try {
                // 注册客户端的Messenger
                Message msg = Message.obtain(null, ExampleService.MSG_REGISTER_CLIENT);
                msg.replyTo = mMessenger;
                mService.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        public void onServiceDisconnected(ComponentName className) {
            mService = null;
            mBound = false;
        }
    };

    public void sayHello(View v) {
        if (!mBound) return;
        try {
            Message msg = Message.obtain(null, ExampleService.MSG_SAY_HELLO, 0, 0);
            mService.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button = findViewById(R.id.say_hello_button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sayHello(v);
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        bindService(new Intent(this, ExampleService.class), mConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mBound) {
            // 取消注册客户端的Messenger
            try {
                Message msg = Message.obtain(null, ExampleService.MSG_UNREGISTER_CLIENT);
                mService.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            unbindService(mConnection);
            mBound = false;
        }
    }
}

在这个示例中,客户端通过点击按钮向服务发送一个"Say Hello"消息。服务接收到消息后,通过客户端注册的Messenger回复一条消息。客户端接收到服务的回复后,显示一个Toast。

这个完整的例子展示了如何使用Messenger实现Android服务与客户端之间的双向通信。

相关推荐
百锦再29 分钟前
Android Studio开发 SharedPreferences 详解
android·ide·android studio
青春给了狗41 分钟前
Android 14 修改侧滑手势动画效果
android
CYRUS STUDIO1 小时前
Android APP 热修复原理
android·app·frida·hotfix·热修复
火柴就是我2 小时前
首次使用Android Studio时,http proxy,gradle问题解决
android
limingade2 小时前
手机打电话时电脑坐席同时收听对方说话并插入IVR预录声音片段
android·智能手机·电脑·蓝牙电话·电脑打电话
浩浩测试一下2 小时前
计算机网络中的DHCP是什么呀? 详情解答
android·网络·计算机网络·安全·web安全·网络安全·安全架构
青春给了狗4 小时前
Android 14 系统统一修改app启动时图标大小和圆角
android
pengyu4 小时前
【Flutter 状态管理 - 柒】 | InheritedWidget:藏在组件树里的"魔法"✨
android·flutter·dart
居然是阿宋6 小时前
Kotlin高阶函数 vs Lambda表达式:关键区别与协作关系
android·开发语言·kotlin
凉、介6 小时前
PCI 总线学习笔记(五)
android·linux·笔记·学习·pcie·pci