bindService简介

Service一般用于不用显示,运行在后台的服务。

startService 是我们最常用的启动Service的方法。而如何让service与其他组件通信呢?一般在一个进程内,可以使用广播的方式让Service与本进程其他Actvity/service进行通信,那么还有更好的方法吗?如果要进行进程间通信(IPC)呢?

bindService就是解决这些问题的。

Binder通信机制介绍

在学习bindService之前,有必要对Binder通信机制有个基本的认识。为了提供系统全局服务,让系统中的任何应用程序都能访问这个全局服务,android设计了这个叫做Binder的client/server的通信结构。

binder通信是一种client-server的通信结构,
    1.从表面上来看,是client通过获得一个server的代理接口(Binder),对server进行直接调用;
    2.实际上,代理接口中定义的方法与server中定义的方法是一一对应的;
    3.client调用某个代理接口中的方法时,代理接口的方法会将client传递的参数打包成为Parcel对象;
    4.代理接口将该Parcel发送给内核中的binder driver.
    5.server会读取binder driver中的请求数据,如果是发送给自己的,解包Parcel对象,处理并将结果返回;
    6.整个的调用过程是一个同步过程,在server处理的时候,client会block住。

对于开发者而言,Binder通信中有个问题需要解决:客户端如何获得服务端的Binder对象应用

Service类已经解决了这个问题

bindService和Binder机制

public boolean bindService(Intent service , ServiceConnection conn, int flags);

public interface ServiceConnection {

public void onServiceConnected(ComponetName name , IBinder service);

public void onServiceDisconnected(ComponentName name);

}

当客户端请求Ams启动某个Service后,该Service如果正常启动,那么Ams就会远程调用ActivityThread类中的ApplicationThread对象,调用的参数包含Service的Binder引用,然后在ApplicationThread中会回调bindService中的conn接口。这样客户端就可以在onServiceConnected()方法中将其参数Service保存为一个全局变量。

这样,客户端(一般是activity)就可以直接访问Service中的public方法和属性了。

BindService Basics

如果要使用BindService,Service必须要实现onBind()回调方法,onBind()返回IBinder对象,这个IBinder对象就是客户端程序中onServiceConnected()方法所需要的参数IBinder。一个客户端可以使用BinderService绑定到一个Service上,此时这个客户端必须提供ServiceConnection的实现,这样才能获得从Service中返回的IBinder。

多个客户端可以绑定到一个Service,但Service只在第一个客户端BindService时才会调用onBind()。后续BindService的客户端获得的IBinder都是从Service第一次调用onBind()中返回的IBinder。

如果Service是bindService启动的(不是startService),那么当最后一个客户端unBindService(),Service将会destroy。

Android官方定义IBinder的几种方式

扩展binder类-Extending the Binder class

如果Service不需要在多个进程间工作,那么你可以实现你自己的Binder类,让客户端(一般是Activity)可以直接调用Service的public方法。(注:在同一个应用程序中,Activity和Service都属于UI线程)

  • 注解:这个方法只有在客户端和Service在同一个应用程序和线程中时才可行,这种情况很常见。例如,这个方法对于一个音乐应用程序将会非常有用,它需要绑定一个Activity到它自己的Service用来以后台播放音乐。

以下为如何设定这个binder类:

1.在你的Service中,创建一个Binder类的实例,实现以下功能之一:

  • 包含客户端可以调用的public方法
  • 返回当前Service的实例,其包含了客户端可以访问的public方法
  • 或返回这个Service包含的另一个类,并含有客户端可以访问的public方法

2.从onBind()回调函数返回这个Binder的实例。

3.在客户端,从onServiceConnected()回调方法接收这个Binder,调用bindService()。

  • 注解:Service和客户端必须在同一个应用程序中的原因是客户端可以计算返回的对象并恰当的调用其APIs。服务和客户端也必须在同一个线程的原因是这种技术不能执行线程间操作。

例如,以下为一个为客户端提供了通过Binder实现接入服务中方法的服务范例:

   public class LocalService extends Service {
// Binder given to clients
private final IBinder mBinder = new LocalBinder();
// Random number generator
private final Random mGenerator = new Random(); /**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
LocalService getService() {
// Return this instance of LocalService so clients can call public methods
return LocalService.this;
}
} @Override
public IBinder onBind(Intent intent) {
return mBinder;
} /** method for clients */
public int getRandomNumber() {
return mGenerator.nextInt(100);
}
}

LocalBinder为客户端提供了getService()方法来取得当前的LocalService实例。这个允许客户端调用服务中的公共方法。例如,客户端可以从服务中调用getRandomNumber()。

以下为,当一个按钮被点击时,一个绑定到LocalService的活动并调用getRandomNumber()方法:

   public class BindingActivity extends Activity {
LocalService mService;
boolean mBound = false; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
} @Override
protected void onStart() {
super.onStart();
// Bind to LocalService
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
} @Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
} /** Called when a button is clicked (the button in the layout file attaches to
* this method with the android:onClick attribute) */
public void onButtonClick(View v) {
if (mBound) {
// Call a method from the LocalService.
// However, if this call were something that might hang, then this request should
// occur in a separate thread to avoid slowing down the activity performance.
int num = mService.getRandomNumber();
Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
}
} /** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() { @Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
} @Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}

使用一个消息传递器-Using a Messenger

如果你需要你的Service能够与远程进程通信,那么你可以使用一个Messenger为你的服务提供接口。这个方法允许你执行进程间通信(IPC)而不需要使用AIDL(当Service要处理多线程的客户端请求时,AIDL更加适合)。

以下为怎么样使用Messenger的总结:

  • Service实现了一个Handler,用来接收每一次客户端发来的请求,并根据请求内容做处理。
  • 客户端使用这个IBinder来实例化这个Messenger(其引用到服务的Handler),客户端可以用来向Service发送Message对象(此处可以理解为客户端向Service发出的请求)。

通过这种方法,在Service没有客户端能调用的“方法”。而是,客户传递“消息”(Message对象),同时服务在其Handler中接收。

以下为服务使用一个Messenger接口的简单范例:

   public class MessengerService extends Service {
/** Command to the service to display a message */
static final int MSG_SAY_HELLO = 1; /**
* Handler of incoming messages from clients.
*/
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO:
Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
}
/**
* Target we publish for clients to send messages to IncomingHandler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler()); /**
* When binding to the service, we return an interface to our messenger
* for sending messages to the service.
*/
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
return mMessenger.getBinder();
}
}

注意Handler中的handleMessage()方法,Service接收客户端发来的Message,基于what成员,决定下一步的处理。

客户端所需做的只是基于Service返回的IBinder创建一个Messenger并使用send()方法发送一条消息。例如,以下为一个简单的Activity范例,其绑定到了Service,并向服务传递了MSG_SAY_HELLO消息:

   public class ActivityMessenger extends Activity {
/** Messenger for communicating with the service. */
Messenger mService = null; /** Flag indicating whether we have called bind on the service. */
boolean mBound;
/**
* Class for interacting with the main interface of the service.
*/
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the object we can use to
// interact with the service. We are communicating with the
// service using a Messenger, so here we get a client-side
// representation of that from the raw IBinder object.
mService = new Messenger(service);
mBound = true;
} public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mService = null;
mBound = false;
}
}; public void sayHello(View v) {
if (!mBound) return;
// Create and send a message to the service, using a supported 'what' value
Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
} @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
} @Override
protected void onStart() {
super.onStart();
// Bind to the service
bindService(new Intent(this, MessengerService.class), mConnection,
Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
}

参考文章:

http://developer.android.com/

Android Service的绑定 基础概念篇 http://www.cnblogs.com/mengdd/archive/2013/03/24/2979710.html

android bindService()的更多相关文章

  1. Android bindservice使用

    package com.example.myact10; import com.example.myact10.MyService.MyBinder; import android.support.v ...

  2. Android BindService中遇到的一个小问题

    今天在使用BindService的时候遇到个小问题,我希望通过Bindservice获取到这个服务,然后执行服务内的某个自定义方法,如下: if(bindService==null){ Intent ...

  3. Android service ( 一 ) 三种开启服务方法

    一. Service简介 Service是android 系统中的四大组件之一(Activity.Service.BroadcastReceiver.ContentProvider),它跟 Activ ...

  4. 新建android系统服务

    一.Android系统服务 Android提供了很多系统服务:如ActivityManger,PowerManger,WindowManger,WifiManger等等. 这些服务都是系统启动开始就一 ...

  5. 深入理解Android的startservice和bindservice

    一.首先,让我们确认下什么是service?         service就是android系统中的服务,它有这么几个特点:它无法与用户直接进行交互.它必须由用户或者其他程序显式的启动.它的优先级比 ...

  6. 【Android 界面效果34】Android里Service的bindService()和startService()混合使用深入分析

    .先讲讲怎么使用bindService()绑定服务 应用组件(客户端)可以调用bindService()绑定到一个service.Android系统之后调用service的onBind()方法,它返回 ...

  7. Android开发之bindService()侦听service内部状态

    在Android开发之bindService()通信的基础上,实现bindService()方法侦听service内部状态. 实现侦听service内部状态,使用的是回调机制 1.首先实现一个接口 p ...

  8. 理解Android的startservice和bindservice(转)

    一.首先,让我们确认下什么是service? service就是android系统中的服务,它有这么几个特点:它无法与用户直接进行交互.它必须由用户或者其他程序显式的启动.它的优先级比较高,它比处于前 ...

  9. 【转】Android中BindService方式使用的理解

    原文网址:http://www.cnblogs.com/onlylittlegod/archive/2011/05/15/2046652.html 最近学习了一下Android里面的Service的应 ...

随机推荐

  1. S5PV210启动过程分析

    一.三星官方推荐方式 1.数据手册<S5PV210_iROM_Application_note>中截取:

  2. OPNET安装要点

    最近在做一点网络的仿真工作,需要用到OPNET这个工具,安装了一早上终于安装好了.安装过程如下: 1.安装visual studio 2010:其他版本如vs2005, vs2008也是可以的.vs2 ...

  3. 一个处理Date与String的工具类

    public class DateUtil { private DateUtil(){ } public static final String hhmmFormat="HH:mm" ...

  4. GitHub 入门

    1. CentOS 安装 Github. # sudo yum install skynet 安装之后查看一下版本. # git --version 2. 注册 Github 账号,登录后阅读 Git ...

  5. Scut 进阶:网络模型拓扑

    处理消息流程: 关于是否能用 json 串作为 response? 在最后写消息的时候要加上控制选项,将Response类型,事直接以字节流,还是转json串再转字节流的方式进行编码了,如果要转jso ...

  6. Linux的时钟管理

    本文转自博客园zhenwenxian的Linux时间管理,很详细,写得很不错,对初学者还是有很大帮助的. 时间管理在内核中占有非常重要的地位.相对于事件驱动,内核中有大量的函数都是基于时间驱动的.内核 ...

  7. Seek the Name, Seek the Fame

    poj2752:http://poj.org/problem?id=2752 题意:给你一个串,让你求前n个字符和后n个字符相同的n有多少,从小到大输出来. 题解:这一题要深刻理解KMP的next数组 ...

  8. 海园帮忙写的JQUERY功能,实现了我们想要的,我觉得有点屌哟~~

    需求就是为了可以在WEB在线更新代码期间,如果执行时间较长的话, 就在提交按钮之后,按钮变为灰色. 同时,一个DIV里每隔两秒刷新输出. 当更新完成之后(检测文档中的关键字串),按钮变为可提交状态~~ ...

  9. VB编写的验证码生成器

    验证码(CAPTCHA)是“Completely AutomatedPublicTuring test to tell Computers andHumansApart”(全自动区分计算机和人类的图灵 ...

  10. C++读写文件并排序

    比如一条记录是 1987 9 2 1988 8 26 代表公司员工生日 然后需要读入到系统 现在需要放入容器,并且排序 最后输出到新的文件中,按照年龄由大到小. #include "stda ...