职业IT人-IT人生活圈

 找回密码
 成为会员
搜索
查看: 426|回复: 1

Android Service 之三(Bind Service,使用 Messenger)

[复制链接]
能文能武 发表于 2011-8-29 09:44 | 显示全部楼层 |阅读模式
第二种:使用 Messenger
这种情况适用于你想实现进程间通信的场合,它分以下几个步骤:
① service 内部需要有一个 Handler 的实现,它被用来处理从每一个 client 发送过的来请求
② 通过这个 Handler ,来生成一个 Messenger
③ 在 service 的onBind() 方法中,需要向 client 返回由该 Messenger 生成的一个 IBinder 实例
④ client 使用从 service 返回的 IBinder 实例来初始化一个 Messenger, 然后使用该 Messenger 与 service 进行通信
⑤ service 通过它自身内部的 Handler 实现(Handler 人 handleMessage() 方法中)来处理从 client 发送过来的请求

下面给出一实例进行说明,该实现由两个工程组成:
① BindServiceDemo_Client: 该工程中只包含一个Activity,用来绑定另一个工程中的 Service
② BindServiceDemo_Service:该工程中只包含一个Service
在实例中, Client 与 Service 中都有一个Messenger ,所以可以进行两者的互相请求与应答。话不多说,贴上部分源码:
① BindServiceDemoClient 中:
  
// client 端 Handler 的实现   
private class IncomingHandler extends Handler {   
        /*  
         * 处理从Service发送至该Activity的消息  
         * (non-Javadoc)  
         * @see android.os.Handler#handleMessage(android.os.Message)  
         */  
        @Override  
        public void handleMessage(Message msg) {   
            switch (msg.what) {   
                case MSG_SET_VALUE:   
                    Toast.makeText(BindServiceDemoClient.this,   
                            "set value as: " + msg.arg1, Toast.LENGTH_SHORT)   
                            .show();   
                    break;   
                default:   
                    super.handleMessage(msg);   
            }   
        }   
    }  

// client 端 Handler 的实现
private class IncomingHandler extends Handler {
                /*
                 * 处理从Service发送至该Activity的消息
                 * (non-Javadoc)
                 * @see android.os.Handler#handleMessage(android.os.Message)
                 */
                @Override
                public void handleMessage(Message msg) {
                        switch (msg.what) {
                                case MSG_SET_VALUE:
                                        Toast.makeText(BindServiceDemoClient.this,
                                                        "set value as: " + msg.arg1, Toast.LENGTH_SHORT)
                                                        .show();
                                        break;
                                default:
                                        super.handleMessage(msg);
                        }
                }
        }
  
// client 端 ServiceConnection 的实现   
private ServiceConnection myRemoteServiceConnection = new ServiceConnection() {   
        public void onServiceConnected(android.content.ComponentName name,   
                android.os.IBinder service) {   
            updateLog("myServiceConnection.onServiceConnected");   
            // 客户端 与 服务 不在同一个进程中的话,所以不可以进行显示强制类型转换的,   
            // 因为,通过Debug,可以发现此时传进来的 Service 的类型是 BinderProxy   
            isBound = true;   
            // 使用从Service返回的IBinder来生成一个Messenger   
            Messenger serviceMessenger = new Messenger(service);   
            // 生成一个Message   
            Message msg = Message.obtain();   
            msg.what = MSG_REGISTER_CLIENT;   
            msg.replyTo = messenger;   
            try {   
                // 向Service 发送Message   
                serviceMessenger.send(msg);   
            } catch (RemoteException e) {   
                e.printStackTrace();   
            }   
  
            msg = Message.obtain();   
            msg.what = MSG_SET_VALUE;   
            msg.replyTo = messenger;   
            msg.arg1 = 10;   
            try {   
                serviceMessenger.send(msg);   
            } catch (RemoteException e) {   
                e.printStackTrace();   
            }   
        };  

// client 端 ServiceConnection 的实现
private ServiceConnection myRemoteServiceConnection = new ServiceConnection() {
                public void onServiceConnected(android.content.ComponentName name,
                                android.os.IBinder service) {
                        updateLog("myServiceConnection.onServiceConnected");
                        // 客户端 与 服务 不在同一个进程中的话,所以不可以进行显示强制类型转换的,
                        // 因为,通过Debug,可以发现此时传进来的 Service 的类型是 BinderProxy
                        isBound = true;
                        // 使用从Service返回的IBinder来生成一个Messenger
                        Messenger serviceMessenger = new Messenger(service);
                        // 生成一个Message
                        Message msg = Message.obtain();
                        msg.what = MSG_REGISTER_CLIENT;
                        msg.replyTo = messenger;
                        try {
                                // 向Service 发送Message
                                serviceMessenger.send(msg);
                        } catch (RemoteException e) {
                                e.printStackTrace();
                        }

                        msg = Message.obtain();
                        msg.what = MSG_SET_VALUE;
                        msg.replyTo = messenger;
                        msg.arg1 = 10;
                        try {
                                serviceMessenger.send(msg);
                        } catch (RemoteException e) {
                                e.printStackTrace();
                        }
                };
  
② BindServiceDemoService 中:
   
// service 端的 Handler 的实现   
private class IncomingHandler extends Handler {   
  
        @Override  
        public void handleMessage(Message msg) {   
            switch (msg.what) {   
                case MSG_REGISTER_CLIENT:   
                    allClients.add(msg.replyTo);   
                    break;   
                case MSG_UNREGISTER_CLIENT:   
                    allClients.remove(msg.replyTo);   
                    break;   
                case MSG_SET_VALUE:   
                    int value = msg.arg1;   
                    for (int i = 0; i < allClients.size(); i++) {   
                        try {   
                            allClients.get(i).send(   
                                    Message.obtain(null, MSG_SET_VALUE, value,   
                                            0));   
                        } catch (RemoteException e) {   
                            allClients.remove(i);   
                        }   
                    }   
                    break;   
                default:   
                    super.handleMessage(msg);   
            }   
        }   
  
    }  

// service 端的 Handler 的实现
private class IncomingHandler extends Handler {

                @Override
                public void handleMessage(Message msg) {
                        switch (msg.what) {
                                case MSG_REGISTER_CLIENT:
                                        allClients.add(msg.replyTo);
                                        break;
                                case MSG_UNREGISTER_CLIENT:
                                        allClients.remove(msg.replyTo);
                                        break;
                                case MSG_SET_VALUE:
                                        int value = msg.arg1;
                                        for (int i = 0; i < allClients.size(); i++) {
                                                try {
                                                        allClients.get(i).send(
                                                                        Message.obtain(null, MSG_SET_VALUE, value,
                                                                                        0));
                                                } catch (RemoteException e) {
                                                        allClients.remove(i);
                                                }
                                        }
                                        break;
                                default:
                                        super.handleMessage(msg);
                        }
                }

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

@Override
public IBinder onBind(Intent intent) {
    return messenger.getBinder();
}
下面来看运行效果图(Debug模式):
首先,启动 BindServiceDemoClient


此时,所有的进程如下:


最下面的那个进程即为 BindServiceDemoClient 工程对应的进程,而且还没有 BindServiceDemoService 工程的进程。下面,点击 "Bind Service" 的按钮,当执行下图中的断点时,请注意右上角 service 的类型(BindProxy),这也从一个方面说明了为什么在 IPC 的时候不可以使用 IBinder 来实现。


按F8继续执行,会得到如下截图:


  
此时,再来看一下系统中的进程情况:


会发现,在最下面多了一个 BindServiceDemoService 工程的进程,这就说明了 client 与 service 是在不同的进程内的,这也正是本例子的意图:使用 Messenger 在不同进程间进行通信。

现在通过 DDMS 控制台,直接将 com.archer.rainbow.service 进程杀掉,来模拟系统资源少而急需回收系统资源的情况,如下:


系统会输出如下日志:


之后,当系统资源充足的时候,会自己重新启动该进程,如下图:


同时,系统输出的日志为:


另外,需要注意的是,当我们通过界面点击 "Unbind Service" 的时候,虽然服务被解绑了,但是系统并没有立即将 com.archer.rainbow.service 这一进程给杀掉:




但若此时,通过 DDMS 控制台,直接将该进程杀掉的话,系统也不会重新启动该进程





注意与上面对应的日志进行比对,你会发现它少了 "Scheduling restart........" 的这条日志。

PS:若想将 service 在另一个进程中启动,你也可以在声明 Service 的时候,使用 "android:process=":remote"" 这种方式来实现。
BindServiceDemo_Client.zip (54.3 KB)
下载次数: 12
BindServiceDemo_Service.zip (43.9 KB)
下载次数: 9

走失的猫咪 发表于 2011-8-29 09:44 | 显示全部楼层
推荐链接
3G培训就业月薪平均7K+,不3K就业不花一分钱!

20-30万急聘多名天才Java/MTA软件工程师
见证又一个准百万富翁的诞生!

您需要登录后才可以回帖 登录 | 成为会员

本版积分规则

QQ|手机版|小黑屋|网站帮助|职业IT人-IT人生活圈 ( 粤ICP备12053935号-1 )|网站地图
本站文章版权归原发布者及原出处所有。内容为作者个人观点,并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是信息平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽造成漏登,请及时联系我们,我们将根据著作权人的要求立即更正或者删除有关内容。

GMT+8, 2024-4-27 17:26 , Processed in 0.111454 second(s), 20 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表