如果Service要和另一个进程中的组件通信,可以使用Messenger,这样也可以实现IPC(不需要AIDL)。
1、在service中实现一个Handler的类,用来响应客户端(绑定服务的组件)的请求。
2、这个Handler是用来创建Messenger对象的(相当于对Handler的引用)。
3、Messenger创建一个IBinder对象,在service的onBind()方法中返回给客户端。
4、在客户端成功绑定的回掉方法中利用返回的IBinder实例化一个Messenger对象,可以发送message给service,具体的实现在前面的Handler的handleMessage()方法中实现。
例子
在service中
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(); } }在Activity中
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; } } }
官方建议
Additional notes
Here are some important notes about binding to a service:
- You should always trap
DeadObjectException
exceptions, which are thrown when the connection has broken. This is the only exception thrown by remote methods. - Objects are reference counted across processes.
- You should usually pair the binding and unbinding during matching bring-up and tear-down moments of the client's lifecycle. For example:
- If you only need to interact with the service while your activity is visible, you should bind during
onStart()
and unbind duringonStop()
. - If you want your activity to receive responses even while it is stopped in the background, then you can bind during
onCreate()
and unbind duringonDestroy()
. Beware that this implies that your activity needs to use the service the entire time it's running (even in the background), so if the service is in another process, then you increase the weight of the process and it becomes more likely that the system will kill it.
Note: You should usually not bind and unbind during your activity's
onResume()
andonPause()
, because these callbacks occur at every lifecycle transition and you should keep the processing that occurs at these transitions to a minimum. Also, if multiple activities in your application bind to the same service and there is a transition between two of those activities, the service may be destroyed and recreated as the current activity unbinds (during pause) before the next one binds (during resume). (This activity transition for how activities coordinate their lifecycles is described in the Activities document.) - If you only need to interact with the service while your activity is visible, you should bind during
其实上面的建议我就看懂两点
1、如果只有在activity可见的时候才跟service交互,那么就在onStart()
绑定, onStop()中解绑。
2、如果需要在activity不可见的时候,被保存在后台的时候依然要响应service,那么在
onCreate()
绑定, onDestroy()中解绑。
3、不要再
onResume()
andonPause()绑定和解绑,具体原因看上面,我好像看的也不是很懂,大致意思是如果有多个activity绑定service,如果这个解绑了,在onPause()之后有可能被系统干掉,但是后面的那个activity还没有绑定,这就造成了浪费。