Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 664|回复: 0

[实例教程]Android Service (Bind Service,使用 Messenger)

[复制链接]

该用户从未签到

发表于 2011-10-22 13:05:08 | 显示全部楼层 |阅读模式
上次讲了第一种 Bind Service 的实现方式,今天讲
第二种:使用 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 中:

java代码


// 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);

                        }

                }

        }




Java代码 // 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 中:

Java代码


// 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);

                        }

                }



        }






Java代码
@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.33 KB, 下载次数: 1)

BindServiceDemo_Service.zip (43.93 KB, 下载次数: 1)




2011-9-14 13:38:43 上传 2011-9-14 13:38:39 上传 2011-9-14 13:38:28 上传
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2024-6-15 15:12 , Processed in 0.356019 second(s), 34 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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