android bindService()
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方法
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,用来接收每一次客户端发来的请求,并根据请求内容做处理。
- Service通过它的Handler接收每一个Message——更确切的说,是在handleMessage()方法中接收。
通过这种方法,在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;
}
}
}
参考文章:
Android Service的绑定 基础概念篇 http://www.cnblogs.com/mengdd/archive/2013/03/24/2979710.html
android bindService()的更多相关文章
- Android bindservice使用
package com.example.myact10; import com.example.myact10.MyService.MyBinder; import android.support.v ...
- Android BindService中遇到的一个小问题
今天在使用BindService的时候遇到个小问题,我希望通过Bindservice获取到这个服务,然后执行服务内的某个自定义方法,如下: if(bindService==null){ Intent ...
- Android service ( 一 ) 三种开启服务方法
一. Service简介 Service是android 系统中的四大组件之一(Activity.Service.BroadcastReceiver.ContentProvider),它跟 Activ ...
- 新建android系统服务
一.Android系统服务 Android提供了很多系统服务:如ActivityManger,PowerManger,WindowManger,WifiManger等等. 这些服务都是系统启动开始就一 ...
- 深入理解Android的startservice和bindservice
一.首先,让我们确认下什么是service? service就是android系统中的服务,它有这么几个特点:它无法与用户直接进行交互.它必须由用户或者其他程序显式的启动.它的优先级比 ...
- 【Android 界面效果34】Android里Service的bindService()和startService()混合使用深入分析
.先讲讲怎么使用bindService()绑定服务 应用组件(客户端)可以调用bindService()绑定到一个service.Android系统之后调用service的onBind()方法,它返回 ...
- Android开发之bindService()侦听service内部状态
在Android开发之bindService()通信的基础上,实现bindService()方法侦听service内部状态. 实现侦听service内部状态,使用的是回调机制 1.首先实现一个接口 p ...
- 理解Android的startservice和bindservice(转)
一.首先,让我们确认下什么是service? service就是android系统中的服务,它有这么几个特点:它无法与用户直接进行交互.它必须由用户或者其他程序显式的启动.它的优先级比较高,它比处于前 ...
- 【转】Android中BindService方式使用的理解
原文网址:http://www.cnblogs.com/onlylittlegod/archive/2011/05/15/2046652.html 最近学习了一下Android里面的Service的应 ...
随机推荐
- table 表格隔行换色实现
table 表格隔行换色实现 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "htt ...
- ExtJs MVC应用架构示例
项目目录结构 (源码)2. app.js Ext.Loader.setConfig({ enabled : true, paths : { 'Ext' : 'extjs', 'App' : 'app' ...
- get set
关于C# get set的文章很多,但是笔者的这篇文章有它的特别之处,笔者用简单的语言把c# get set讲述的十分明了. C# get set释一:属性的访问器包含与获取(读取或计算)或设置(写) ...
- Regularized Linear Regression with scikit-learn
Regularized Linear Regression with scikit-learn Earlier we covered Ordinary Least Squares regression ...
- h.264参考图像列表、解码图像缓存
1.参考图像列表(reference picture list) 一般来说,h.264会把需要编码的图像分为三种类型:I.P.B,其中的B.P类型的图像由于采用了帧间编码的这种编码方式,而帧间编码又是 ...
- 萬用表檢測MOS管好壞的簡便方法
在開發LED驅動電源時難免不會接觸到MOS管,它又是一個相當脆弱的器件.往往有時故障就是因為它罷工了.以下的一點經驗希望對大家有所幫助. 1.用黑表筆接在D極上 ,紅表筆接在S極上 , 一般有一個5 ...
- KEIL C51高级编程
第一节 绝对地址访问C51提供了三种访问绝对地址的方法: 1. 绝对宏:在程序中,用“#include”即可使用其中定义的宏来访问绝对地址,包括:CBYTE.XBYTE.PWORD.DBYTE.CWO ...
- html5中使用标签支持视频播放
<!--定义视频--> <!-- <video src="E:/ext-4.2.1.883/learnHtml5/Wildlife.wmv" control ...
- 【HDOJ】3285 Convex Hull of Lattice Points
凸包模板题目. /* 3285 */ #include <iostream> #include <cstdio> #include <cstring> #inclu ...
- UVA253 Cube painting(数学)
题目链接. 分析: 用的<训练指南>上的方法.详见P17. 从6个面中选一个做顶面,再从剩下的4个面中选1个做正面,则此正方体唯一确定. 需要枚举共6*4=24种. #include &l ...