Android开发文档翻译之——Bound Services
来源:互联网 发布:广数928螺纹编程格式 编辑:程序博客网 时间:2024/05/19 01:06
绑定状态下的service
Bound Service是一种c/s接口中的server端。其允许其他组件绑定到service,发送请求,接收响应,甚至进行进程间的交互(IPC)Bound Service通常只在有其他组件需要服务时运行,并不单独运行在后台。
本文档主要内容是如何创建一个bound service,包括在其他应用中绑定该service。如果你对service的基础概念不是太熟悉,建议你先看看我的另外一篇博客Android开发文档翻译之-Services
基础概念
Bound Service是service的一种实现方式。通过该方式其他应用程序可以绑定到该service并与其交互。你需要覆写onBind()函数来提供该功能。这个方法返回一个IBinder对象用来提供与service交互的接口。
client端程序通过调用bindService()来绑定service。调用该方法需要提供一个ServiceConnection对象,来监视与service的连接状态。bindService()会立即返回,并且在系统创建连接后回调onServiceConnected()函数,并且返回IBinder对象来供client端交互。
多个client端可以在同一时间绑定同一个service。然而用户只会接到一个onBind()回调。除了第一个绑定到service的对象会通过onBind()得到一个IBinder对象,其他时候系统都会直接将这个IBinder对象返回,并且不再调用onBind()函数。当最后一个client解绑时,系统会销毁这个service。
当你实现你的bound service时,最重要的一步是定义IBinder接口。以下是几种定义IBinder接口的方式:
1.继承Binder类
通常而言,如果你的service仅提供给你自己的应用程序使用,你应该提供你的接口通过继承Binder类,并且在onBInd()中返回。client端接收这个Binder对象,并且可以直接访问它的共有方法以及service中的共有方法。
2.使用Messenger
如果你需要一个在不同进程间工作的接口,你可以通过Messenger来创建service。这种方式下,service定义一个Handler来响应不同类型的Message。Handler类是用来提供一个IBinder对象的基础。通过Messenger,client端可以发送消息到server端。同样的,client端可以定义一个Messenger来接收service的消息回调。
注:这是IPC机制的一种简单方式。由于Messenger将所有的请求放入一个单线程的消息队列中,因此你设计的service是线程安全的。
3.使用AIDL
AIDL(Android Interface Define Language)是一种描述进程间通信的一种语言。刚刚介绍的Messenger就是一种基于AIDL的技术。如果你希望你的service能够处理多个并发的请求,那么你可以直接使用AIDL。这种情况下,你的service必须有多线程的执行能力并且需要是线程安全的。
PS:大部分程序是不需要AIDL的。因为AIDL需要拥有多线程处理能力,并且会使得情况更加复杂。因此,AIDL对于绝大部分应用是不适用的。本文也不打算介绍该技术,如果你确定你要使用该技术,请查看我的另外一篇博文:Android开发文档翻译之——AIDL
继承Binder类
你可以按以下步骤来实现:
1.在service中,创建一个Binder的实例,该Binder类需要满足:1)包含公有方法供client端调用;2)返回当前service的实例,该实例中包含公有方法给client端调用;3)如果不满足2),则返回一个service的内部类的实例,该内部类中提供了公有方法供client端调用。
2.在onBind()方法中返回Binder的实例。
3.在client端,通过onServiceConnected()函数接收Binder对象并且调用相关接口方法。
ps:service和client需要在同一应用的一个理由是你需要强制转换返回的IBinder对象。service和client必须要在相同的进程,因为该技术没有提供任何跨进程间通信的方式。
以下是一个继承IBinder类的示例:
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的实例。因此client端可以调用service的公有方法。例如,getRandomNumber()。
以下是一个activity绑定service并调用其公有方法的相关代码:
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; } };}
使用Messenger
如果你的service需要和远端进程进行通信,那么你需要使用Messenger为你的service提供一个接口。这个技术允许你在不通过AIDL技术的前提下完成IPC。
以下是使用Messenger的步骤:
1.service实现Handler类来接收client端的回调。
2.通过该Handler类产生Messenger的实例。
3.Messenger产生一个IBinder类的实例并在onBinder()中返回。
4.client端使用IBinder对象来实例一个Messenger对象(该对象持有Handler的引用),通过该对象来向service端发送消息。
5.service在handlerMessage()中执行相关操作。
以下是一个使用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(); }}
client端的代码如下:
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; } }}
上面两段代码较为简单,就不做过多的解释了。
Messenger和AIDL的比较
当你需要进程间通信时,使用Messenger是比AIDL更为简单的一种方式,因为Messenger依次的将请求放进请求队列中,而AIDL同时的将所有请求发送至service,因此你需要处理多线程的问题。
大部分应用程序不需要处理多线程情况,因此Messenger是更好的选择。如果你确实要在多线程情况下处理问题,那么使用AIDL来实现吧。
管理Bound Service的生命周期
Bound Service的生命周期如上图所示,在此不再赘述。
- Android开发文档翻译之——Bound Services
- Android开发文档翻译之-Services
- Android官方文档之Bound Services
- Android 官方文档 - Bound Services
- Android开发指导文档(译)--Bound Services
- Android 开发指导文档(译)-- Bound Services
- Android开发指导文档(译)--Bound Services
- Android Service基础之Bound Services
- [翻译]API Guides - Bound Services
- Android学习笔记18——Bound Services
- Android官方文档-Bound Services(绑定服务)
- Service 之 Bound Services
- Android 开发文档 程序基础 ——Services组件
- android services启动方式 官方文档翻译
- Android开发文档翻译
- 【Android官方文档】翻译Android官方文档-Services(二)
- Unity开始android开发之旅——官方文档翻译
- Android官方文档之Services
- Java中&&和&以及||和|的区别
- hdu4585splay
- 4种进程间通信方式详解
- JS页面跳转(转载)
- Android自定义View或ViewGroup的流程
- Android开发文档翻译之——Bound Services
- Visual Studio 2015 使用时的一些错误
- everything is object
- 【POJ 1765】 November Rain(离散化+扫描线)
- SpringMVC介绍之Validation
- LeetCodet题解--18. 4Sum(4个数的和)
- hdu4585(Treap)
- 第五届计算机职业资格认证考试CCF (第一题)
- 欢迎使用CSDN-markdown编辑器