使用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里面的内容。
时间: 2024-10-11 22:50:29

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

配置隔离组使二层之间不能相互通信,但可以与外部网络通信。

组网要求:hostA hostB hostC 分别与Device的端口g1/0/1,g1/0/2,g1/0/3相连,Device通过g1/0/4与外部网络相连,现要求hostA hostB hostC 三者之间不能相互通信,但可与外部网络通信.配置步骤如下:1.创建隔离组2<Device>system-view[Device]port-isolate group 2 2.将端口g1/0/1,g1/0/2,g1/0/3加入隔离组2中[Device]int g1/0/1[Device-Gigab

配置隔离组使二层之间不能相互通信,但能与外层互通

一.配置隔离信息1.创建如下图的网络结构图,并配置IP地址:2.配置交换机隔离信息: 3.查看交换机配置信息:4.验证配置隔离组二层之间不能相互通信,但能与外层互通结果: 原文地址:https://blog.51cto.com/14223499/2364328

Activity和Service之间只相差了一个Window

从使用的角度来说: - Activity主要处理需要用户参与的任务 - Service主要后台处理一些不需要用户参与的任务 从实现角度来看,是什么造成了它们之间的区别,我很好奇的翻了翻源码,发现: Activity和Service 都是由共同的祖先派生下来的,其实Activty和Service之间最大的区别是 Activity包含了一个Window,但是Service没有. 那么Window是如何和Activity勾搭上的呢? 1. Activity里面所有的View都是放在Window里面管理

activity 与 service 之间的通信

activity和service通信:通过binder 举个我实际项目中的例子:在service中下载更新应用 首先是下载更新apk的service: public class UpdateVersionService extends Service { private final String tag = "young"; private Context context = this; private BaseApplication application; private Down

配置隔离组使二层交换机之间不能相互通信,但可以连接外网

任务要求:小区用户Host A.Host B.Host C分别与Device的端口GigabitEthernet 1/0/1.GigabitEthernet 1/0/2 .GigabitEthernet 1/0/3 相连, Device 设备通过GigabitEthernet 1/0/4 端口与外部网络相连.现需要实现小区用户Host A.Host B和Host C彼此之间二层报文不能互通,但可以和外部网络通信.任务实施:1.将小区用户Host A.Host B.Host C分别与Device的

线程之间的相互通信

1 /* 2 线程的通信,互相调用 两个线程 3 需求: 生产者 消费者 , 生产一个产品 就消费一个产品 , 产品是共享的 4 5 6 */ 7 //产品类 8 class Product{ 9 10 String name; //名字 11 12 double price; //价格 13 14 boolean flag = false; //产品是否生产完毕的标识,默认情况是没有生产完成. 15 16 } 17 18 //生产者 19 class Producer extends Thre

【思科百难】RIP两个版本之间能够相互通信?

配置两台路由器,A&B.A-RIPv1, B-RIPv2 配置如下: A Loo0:1.1.1.1 32     g0/0/0 12.12.12.1 B Loo0:2.2.2.2 32    g0/0/0 12.12.12.2 问:A ping 2.2.2.2 与B ping 1.1.1.1,谁通谁不通? 我们先看routing-table [RTA]dis ip rouRoute Flags: R - relay, D - download to fib--------------------

配置隔离组使二层之间不能相互通信,但都可以与外部通信

组网需求如图所示小区用户Host A.Host B.Host C分别与Device的端口GigabitEthernet 1/0/1.GigabitEthernet 1/0/2 .GigabitEthernet 1/0/3 相连,Device 设备通过GigabitEthernet 1/0/4 端口与外部网络相连.现需要实现小区用户Host A.Host B和Host C彼此之间二层报文不能互通,但可以和外部网络通信.2.配置步骤及验证配置如图所示3.验证结果如图所示 原文地址:https://b

配置相同VLAN之间能够相互通信

一.配置要求? Host A 和Host C 属于部门A,但是通过不同的设备接入公司网络:Host B 和Host D 属于部门B,也通过不同的设备接入公司网络.? 为了通信的安全性,也为了避免广播报文泛滥,公司网络中使用 VLAN 技术来隔离部门间的二层流量.其中部门A 使用VLAN 100,部门B 使用VLAN 200.? 现要求不管是否使用相同的设备接入公司网络,同一 VLAN 内的主机能够互通,即Host A 和Host C 能够互通,Host B 和Host D 能够互通.1.创建如下