转载

Android Service 之 Bound Services

A bound Service 提供了一种CS模式的Service。A bound service allows components (such as activities) to bind to the service, send requests, receive responses, and even perform interprocess communication

Server--Extend a Service, 然后实现onBind()方法,返回IBinder对象。

Client--bindService(),然后必须实现ServiceConnection接口,其具有两个方法,onServiceConnected(),可通知连接服务的状态,并返回IBinder对象。

其中onBinder只在第一次服务被连接时才会被调用,之后将直接返回IBinder对象。

当最后一个client unbind时,系统将destroy 该Service.

Creating a Bound Service

  • 继承Binder类

    然后将它的一个实例作为onBind()返回值。适用于Server和Client在同一进程内。

创建Server

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

Tip: 在LocalBinder中提供了getService()方法,使得客户端可以获得Service的实例,这样就可以调用Service的公共方法。

Client调用:

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;   }  }; }  

可注意到Service的bind,使用以及unBind()的使用。

  • 使用Messenger

    在Service中Create 一个Handler,然后可以接收和处理不同的Message type,同时Messenger 也可返回一个IBinder对象给客户端。此外,客户端也可定义自己的Messenger,然后Service可以发送Message以便返回结果。最简单的实现IPC通信。适用于跨进程。

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();  } }  

以下是Messenger的定义

Reference to a Handler, which others can use to send messages to it. This allows for the implementation of message-based communication across processes, by creating a Messenger pointing to a Handler in one process, and handing that Messenger to another process.

意思是它是对Handler的引用,其他组件可通过它发送消息到handler。允许基于message的handle IPC。它是对Binder的简单包装。

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;   }  } }  

就是一个事件传递。

  • 使用AIDL

    上个使用Messenger的方式,底层结构也是使用AIDL。但Messenger则只是依次处理。但若想同时处理,直接使用AIDL。适用于跨进程。

Tip: 大部分应用无需使用AIDL来创建bound service, 它可能需要多线程处理能力以及更复杂的实现。

Caution:Only activities, services, and content providers can bind to a service—you cannot bind to a service from a broadcast receiver.

bindService(intent, mConnection, Context.BIND_AUTO_CREATE);第三个参数BIND_AUTO_CREATE指create service if its not already alive. 还可以是BIND_DEBUG_UNBIND, BIND_NOT_FOREGROUD, 或者0。

建议:you should bind during onStart() and unbind during onStop().如果希望在App可见时。若想在activity接收响应在stopped时候,可bind during onCreate() and unbind during onDestroy().

正文到此结束
Loading...