2025年3月25日 星期二 甲辰(龙)年 月廿四 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > 安卓(android)开发

使用Messenger进行Activity与Service之间的相互通信

时间:03-14来源:作者:点击数:7
CDSY,CDSY.XYZ

在Android开发中,有时候我们需要让一个Activity绑定一个Service,进行两者之间的通信。当Activity绑定成功以后,就可以调用Service中的public(或有对应可见级别)的方法。如果Service想把一些信息反馈给Activity,则需要将Activity的Listener传递给Service,由Service负责调用。

这样的做法是可以实现功能的,但有一些缺憾。

首先,Service需要把被调用的方法做成public的,不利于隐藏实现。

第二,调用显得凌乱,在Activity中调用了Service的方法,或者在Service中调用Activity的方法。

所以,developer文档提供了另外一种方式,使用Messenger。API Demos也给出了实现的示例,但该示例没有给出Service如何回应Activity部分的实现,只是给了一段提示性的说明文档:

https://developer.android.com/guide/components/bound-services.html

Notice that this example does not show how the service can respond to the client. If you want the service to respond, you need to also create a Messenger in the client. When the client receives the onServiceConnected() callback, it sends a Message to the service that includes the client's Messenger in the replyTo parameter of the send() method.

根据这个提示,我做了一些实验,走通了Service回应Activity的流程。

Activity与Service之间的通信,无论是Service向Activity发送消息,还是Activity发送消息,都通过Messenger类,这样,Service和Activity就不需要提供public的方法作为通信接口。

首先创建一个工程,实现了如下功能,有一个Activity,上面有三个Button和一个TextView,点击任何一个button,Activity的send messenger就会向Service发送一个message,这个message的replayTo,是Activity的另外一个Messenger, 叫receive messenger。service收到message以后。进行相应的处理,例如生成一个integer,float,string,把处理结果通过receive messenger发送出去,Activity就会收到这个消息。

下面是完整代码,只有3个Class,其他都是AndroidStudio自动生成的。

  • MainActivity
  • public class MainActivity extends AppCompatActivity {
  • /*
  • 标记是否已经绑定Service。
  • Marking whether the service has been bound.
  • */
  • private boolean bServiceConnected;
  • /*
  • 这个Messenger用于向Service发送Message。
  • This Messenger is used to send message to service.
  • */
  • private Messenger mSendMessenger;
  • /*
  • 这个Messenger用于接收服务器发送的Message。
  • This Messenger is used to receive message from service.
  • */
  • private Messenger mReceiveMessenger;
  • private TextView mMessageText;
  • /*
  • 处理从Service收到的Message。
  • Handling Messages received from service.
  • */
  • private Handler mHandler = new Handler() {
  • @Override
  • public void handleMessage(Message msg) {
  • switch (msg.what) {
  • case MessageSource.MSG_CREATE_FLOAT:
  • String strI = (String) msg.obj;
  • mMessageText.setText(strI);
  • break;
  • case MessageSource.MSG_CREATE_INT:
  • String strF = (String) msg.obj;
  • mMessageText.setText(strF);
  • break;
  • case MessageSource.MSG_CREATE_STRING:
  • String strS = (String) msg.obj;
  • mMessageText.setText(strS);
  • break;
  • default:
  • break;
  • }
  • }
  • };
  • @Override
  • protected void onCreate(Bundle savedInstanceState) {
  • super.onCreate(savedInstanceState);
  • setContentView(R.layout.activity_main);
  • mMessageText = (TextView) findViewById(R.id.message_from_service);
  • Button createIntBt = (Button) findViewById(R.id.let_service_create_int);
  • createIntBt.setOnClickListener(new View.OnClickListener() {
  • @Override
  • public void onClick(View view) {
  • handleButtonClick(MessageSource.MSG_CREATE_INT);
  • }
  • });
  • Button createFloatBt = (Button) findViewById(R.id.let_service_create_float);
  • createFloatBt.setOnClickListener(new View.OnClickListener() {
  • @Override
  • public void onClick(View view) {
  • handleButtonClick(MessageSource.MSG_CREATE_FLOAT);
  • }
  • });
  • Button createStringBt = (Button) findViewById(R.id.let_service_create_string);
  • createStringBt.setOnClickListener(new View.OnClickListener() {
  • @Override
  • public void onClick(View view) {
  • handleButtonClick(MessageSource.MSG_CREATE_STRING);
  • }
  • });
  • }
  • @Override
  • protected void onResume() {
  • super.onResume();
  • if (!bServiceConnected) {
  • bindService();
  • }
  • }
  • @Override
  • protected void onPause() {
  • super.onPause();
  • unbindService(mServiceConnection);
  • }
  • private void handleButtonClick(int type) {
  • if (bServiceConnected) {
  • Message msg = new Message();
  • msg.what = type;
  • msg.replyTo = mReceiveMessenger;
  • try {
  • mSendMessenger.send(msg);
  • } catch (RemoteException e) {
  • e.printStackTrace();
  • }
  • } else {
  • Toast.makeText(this, "Service has not been bound.", Toast.LENGTH_SHORT).show();
  • }
  • }
  • private void bindService() {
  • Intent intent = new Intent(getApplicationContext(), MainService.class);
  • bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
  • }
  • private ServiceConnection mServiceConnection = new ServiceConnection() {
  • @Override
  • public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
  • bServiceConnected = true;
  • mSendMessenger = new Messenger(iBinder);
  • mReceiveMessenger = new Messenger(mHandler);
  • }
  • @Override
  • public void onServiceDisconnected(ComponentName componentName) {
  • bServiceConnected = false;
  • mSendMessenger = null;
  • mReceiveMessenger = null;
  • }
  • };
  • }
  • MainService
  • public class MainService extends Service {
  • /*
  • 这个Handler负责接收Activity的Message,收到一个Message时,通过获取Message的replayTo得到一个Messenger实例,
  • 使用这个Messenger向Activity发送Message。
  • This Handler is in charge of receiving Messages sending from Activity. When it receiving a
  • Message, get The replayTo which is a Messenger instance from this Message. Using this Messenger
  • to send Message to Activity.
  • */
  • private Handler mActMsgHandler = new Handler() {
  • @Override
  • public void handleMessage(Message msg) {
  • switch (msg.what) {
  • case MessageSource.MSG_CREATE_INT:
  • createAndSendInt(msg.replyTo);
  • break;
  • case MessageSource.MSG_CREATE_FLOAT:
  • createAndSendFloat(msg.replyTo);
  • break;
  • case MessageSource.MSG_CREATE_STRING:
  • createAndSendString(msg.replyTo);
  • break;
  • default:
  • break;
  • }
  • }
  • };
  • /*
  • 这个Messenger用于向Activity发送Message。
  • This Messenger is used to send Message to Activity.
  • */
  • private Messenger mSendMessenger = new Messenger(mActMsgHandler);
  • /*
  • 假设有耗时的操作需要异步进行。
  • Suppose we have long-running jobs and execute asynchronously.
  • */
  • private Executor mExecutor = Executors.newCachedThreadPool();
  • public MainService() {
  • }
  • @Override
  • public IBinder onBind(Intent intent) {
  • return mSendMessenger.getBinder();
  • }
  • private void createAndSendInt(final Messenger messenger) {
  • mExecutor.execute(new Runnable() {
  • @Override
  • public void run() {
  • Random random = new Random();
  • int ret = random.nextInt();
  • String str = "Give you a int: " + ret;
  • send(MessageSource.MSG_CREATE_INT, str, messenger);
  • }
  • });
  • }
  • private void createAndSendFloat(final Messenger messenger) {
  • mExecutor.execute(new Runnable() {
  • @Override
  • public void run() {
  • Random random = new Random();
  • float ret = random.nextFloat();
  • String str = "Give you a float: " + ret;
  • send(MessageSource.MSG_CREATE_FLOAT, str, messenger);
  • }
  • });
  • }
  • private void createAndSendString(final Messenger messenger) {
  • mExecutor.execute(new Runnable() {
  • @Override
  • public void run() {
  • int len = MessageSource.STRING_SOURCE_ARRAY.length;
  • Random random = new Random();
  • int index = random.nextInt(len);
  • String ret = MessageSource.STRING_SOURCE_ARRAY[index];
  • String str = "Give you a string: " + ret;
  • send(MessageSource.MSG_CREATE_STRING, str, messenger);
  • }
  • });
  • }
  • private void send(int type, String str, Messenger messenger) {
  • Message msg = new Message();
  • msg.what = type;
  • msg.obj = str;
  • try {
  • messenger.send(msg);
  • } catch (RemoteException e) {
  • e.printStackTrace();
  • }
  • }
  • }

还有一个辅助的Class

MessageSource

  • public class MessageSource {
  • public static final int MSG_CREATE_INT = 1;
  • public static final int MSG_CREATE_FLOAT = 2;
  • public static final int MSG_CREATE_STRING = 3;
  • public static final String[] STRING_SOURCE_ARRAY = new String[]{"Awake from dreams",
  • "I find the locked tower high",
  • "Sober from wine", "I see the curtain hanging low",
  • "As last year spring grief seems to grow",
  • "Amid the falling blooms alone stand I",
  • "In the fine rain a pair of swallows fly",
  • "I still remember when I first saw pretty Ping",
  • "In silken dress embroidered with two hearts in a ring",
  • "Revealing lovesickness by touching pipa’s string",
  • "The moon shines bright just as last year",
  • "It did see her like a cloud disappear"};
  • }

应用截图和操作说明,当点击 CREATE A INTEGER按钮时,Activity就会向Service发送一个Message。

Service收到这个Message以后,根据Message的what,产生了一个Integer,然后把这个integer拼接到一个字符串后面。

创建一个Message,然后用收到的Message的replayTo,发送出去。Activity就收到了Service发来的Message,然后更新TextView里面的内容。

CDSY,CDSY.XYZ
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐