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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Messenger进行Activity与Service之间的相互通信相关的知识,希望对你有一定的参考价值。

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
  1 public class MainActivity extends AppCompatActivity {
  2 
  3     /*
  4      标记是否已经绑定Service。
  5      Marking whether the service has been bound.
  6      */
  7     private boolean bServiceConnected;
  8 
  9     /*
 10      这个Messenger用于向Service发送Message。
 11      This Messenger is used to send message to service.
 12      */
 13     private Messenger mSendMessenger;
 14 
 15     /*
 16      这个Messenger用于接收服务器发送的Message。
 17      This Messenger is used to receive message from service.
 18      */
 19     private Messenger mReceiveMessenger;
 20 
 21 
 22     private TextView mMessageText;
 23 
 24     /*
 25      处理从Service收到的Message。
 26      Handling Messages received from service.
 27      */
 28     private Handler mHandler = new Handler() {
 29         @Override
 30         public void handleMessage(Message msg) {
 31             switch (msg.what) {
 32                 case MessageSource.MSG_CREATE_FLOAT:
 33                     String strI = (String) msg.obj;
 34                     mMessageText.setText(strI);
 35                     break;
 36                 case MessageSource.MSG_CREATE_INT:
 37                     String strF = (String) msg.obj;
 38                     mMessageText.setText(strF);
 39                     break;
 40                 case MessageSource.MSG_CREATE_STRING:
 41                     String strS = (String) msg.obj;
 42                     mMessageText.setText(strS);
 43                     break;
 44                 default:
 45                     break;
 46             }
 47         }
 48     };
 49 
 50     @Override
 51     protected void onCreate(Bundle savedInstanceState) {
 52         super.onCreate(savedInstanceState);
 53         setContentView(R.layout.activity_main);
 54 
 55         mMessageText = (TextView) findViewById(R.id.message_from_service);
 56 
 57         Button createIntBt = (Button) findViewById(R.id.let_service_create_int);
 58         createIntBt.setOnClickListener(new View.OnClickListener() {
 59             @Override
 60             public void onClick(View view) {
 61                 handleButtonClick(MessageSource.MSG_CREATE_INT);
 62             }
 63         });
 64 
 65         Button createFloatBt = (Button) findViewById(R.id.let_service_create_float);
 66         createFloatBt.setOnClickListener(new View.OnClickListener() {
 67             @Override
 68             public void onClick(View view) {
 69                 handleButtonClick(MessageSource.MSG_CREATE_FLOAT);
 70             }
 71         });
 72 
 73         Button createStringBt = (Button) findViewById(R.id.let_service_create_string);
 74         createStringBt.setOnClickListener(new View.OnClickListener() {
 75             @Override
 76             public void onClick(View view) {
 77                 handleButtonClick(MessageSource.MSG_CREATE_STRING);
 78             }
 79         });
 80     }
 81 
 82     @Override
 83     protected void onResume() {
 84         super.onResume();
 85         if (!bServiceConnected) {
 86             bindService();
 87         }
 88 
 89     }
 90 
 91     @Override
 92     protected void onPause() {
 93         super.onPause();
 94         unbindService(mServiceConnection);
 95     }
 96 
 97     private void handleButtonClick(int type) {
 98         if (bServiceConnected) {
 99             Message msg = new Message();
100             msg.what = type;
101             msg.replyTo = mReceiveMessenger;
102             try {
103                 mSendMessenger.send(msg);
104             } catch (RemoteException e) {
105                 e.printStackTrace();
106             }
107         } else {
108             Toast.makeText(this, "Service has not been bound.", Toast.LENGTH_SHORT).show();
109         }
110     }
111 
112     private void bindService() {
113         Intent intent = new Intent(getApplicationContext(), MainService.class);
114         bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
115     }
116 
117     private ServiceConnection mServiceConnection = new ServiceConnection() {
118         @Override
119         public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
120             bServiceConnected = true;
121             mSendMessenger = new Messenger(iBinder);
122             mReceiveMessenger = new Messenger(mHandler);
123         }
124 
125         @Override
126         public void onServiceDisconnected(ComponentName componentName) {
127             bServiceConnected = false;
128             mSendMessenger = null;
129             mReceiveMessenger = null;
130         }
131     };
132 }

MainService
 
 1 public class MainService extends Service {
 2 
 3     /*
 4      这个Handler负责接收Activity的Message,收到一个Message时,通过获取Message的replayTo得到一个Messenger实例,
 5      使用这个Messenger向Activity发送Message。
 6      This Handler is in charge of receiving Messages sending from Activity. When it receiving a
 7      Message, get The replayTo which is a Messenger instance from this Message. Using this Messenger
 8      to send Message to Activity.
 9      */
10     private Handler mActMsgHandler = new Handler() {
11         @Override
12         public void handleMessage(Message msg) {
13             switch (msg.what) {
14                 case MessageSource.MSG_CREATE_INT:
15                     createAndSendInt(msg.replyTo);
16                     break;
17                 case MessageSource.MSG_CREATE_FLOAT:
18                     createAndSendFloat(msg.replyTo);
19                     break;
20                 case MessageSource.MSG_CREATE_STRING:
21                     createAndSendString(msg.replyTo);
22                     break;
23                 default:
24 
25                     break;
26             }
27         }
28     };
29 
30     /*
31       这个Messenger用于向Activity发送Message。
32       This Messenger is used to send Message to Activity.
33      */
34     private Messenger mSendMessenger = new Messenger(mActMsgHandler);
35 
36     /*
37      假设有耗时的操作需要异步进行。
38      Suppose we have long-running jobs and execute asynchronously.
39      */
40     private Executor mExecutor = Executors.newCachedThreadPool();
41 
42     public MainService() {
43     }
44 
45     @Override
46     public IBinder onBind(Intent intent) {
47         return mSendMessenger.getBinder();
48     }
49 
50     private void createAndSendInt(final Messenger messenger) {
51         mExecutor.execute(new Runnable() {
52             @Override
53             public void run() {
54                 Random random = new Random();
55                 int ret = random.nextInt();
56                 String str = "Give you a int: " + ret;
57                 send(MessageSource.MSG_CREATE_INT, str, messenger);
58 
59             }
60         });
61     }
62 
63     private void createAndSendFloat(final Messenger messenger) {
64         mExecutor.execute(new Runnable() {
65             @Override
66             public void run() {
67                 Random random = new Random();
68                 float ret = random.nextFloat();
69                 String str = "Give you a float: " + ret;
70                 send(MessageSource.MSG_CREATE_FLOAT, str, messenger);
71             }
72         });
73     }
74 
75     private void createAndSendString(final Messenger messenger) {
76         mExecutor.execute(new Runnable() {
77             @Override
78             public void run() {
79                 int len = MessageSource.STRING_SOURCE_ARRAY.length;
80                 Random random = new Random();
81                 int index = random.nextInt(len);
82                 String ret = MessageSource.STRING_SOURCE_ARRAY[index];
83                 String str = "Give you a string: " + ret;
84                 send(MessageSource.MSG_CREATE_STRING, str, messenger);
85             }
86         });
87     }
88 
89     private void send(int type, String str, Messenger messenger) {
90         Message msg = new Message();
91         msg.what = type;
92         msg.obj = str;
93         try {
94             messenger.send(msg);
95         } catch (RemoteException e) {
96             e.printStackTrace();
97         }
98     }
99 }

 还有一个辅助的Class

 MessageSource

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

 

 应用截图和操作说明,当点击 CREATE A INTEGER按钮时,Activity就会向Service发送一个Message。
Service收到这个Message以后,根据Message的what,产生了一个Integer,然后把这个integer拼接到一个字符串后面。
创建一个Message,然后用收到的Message的replayTo,发送出去。Activity就收到了Service发来的Message,然后更新TextView里面的内容。
技术分享





以上是关于使用Messenger进行Activity与Service之间的相互通信的主要内容,如果未能解决你的问题,请参考以下文章

Android中的IPC方式—— Bundle文件共享Messenger

IPC机制——使用Bundle文件共享Messenger

Android Programming: Pushing the Limits -- Chapter 7:Android IPC -- Messenger

Android 使用Messenger实现跨进程之间通信

Kotlin进程通信------Messenger

Kotlin进程通信------Messenger