在Android编程中,要想实现IPC,有如下几种方法:
1,使用AIDL,在需要实现多线程和并发处理时使用
2,继承Binder类来实现
3,使用Messenger
这一节我们研究Messenger的使用。以后有机会研究前两种。
首先,通过查看Messenger的源代码,我们可以看到它有两个构造函数:
/** * Create a new Messenger pointing to the given Handler. Any Message * objects sent through this Messenger will appear in the Handler as if * {@link Handler#sendMessage(Message) Handler.sendMessage(Message)} had * been called directly. * * @param target The Handler that will receive sent messages. */ public Messenger(Handler target) { mTarget = target.getIMessenger(); }
/** * Create a Messenger from a raw IBinder, which had previously been * retrieved with {@link #getBinder}. * * @param target The IBinder this Messenger should communicate with. */ public Messenger(IBinder target) { mTarget = IMessenger.Stub.asInterface(target); }
Handler
,用来接收客户端的信息
Messenger
对象(它是Handler类中的一个引用,Handler类的成员变量mMessenger指向这个新创建的对象)。IBinder
对象, 服务端的onBind()返回该对象给客户端Message
对象给服务端。handleMessage()
方法来处理。
使用这种方式,不存在客户端调用服务端的“方法”,而是客户端发送“信息”(即Message对象),服务端在它的Handler中接收并处理。
如下是使用Messager的服务端的代码:
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(); } }
上述 handleMessage()
方法就是服务端接收消息并决定如何处理的地方。
客户端只需要使用服务端返回的IBinder创建Messenger对象,然后使用该对象的send()方法发生消息即可。代码如下(先绑定服务,然后发送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; } } }
上述示例没有显示服务端如何响应客户端。如果需要服务端响应的话,需要将客户端创建的Messenger对象赋值给的Message的replyTo参数,如下:
服务端:
public class MessengerService extends Service { public static final int MSG_TAG_REMOTE = 0x110; public static final int MSG_TAG_CLIENT = 0x111; private int mCounter = 0; class ServiceHandler extends Handler{ @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_TAG_REMOTE: Messenger client = msg.replyTo; try { client.send(Message.obtain(null, MSG_TAG_CLIENT, ++mCounter,0)); } catch (RemoteException e) { e.printStackTrace(); } } super.handleMessage(msg); } } final Messenger mMessenger = new Messenger(new ServiceHandler()); /* (non-Javadoc) * @see android.app.Service#onBind(android.content.Intent) */ @Override public IBinder onBind(Intent intent) { return (mMessenger == null) ? null : mMessenger.getBinder(); } }
客户端:
public class MessengerServceActivity extends Activity { private TextView mTextView; private Messenger mServiceMessenger; final Messenger mClientMessenger = new Messenger(new ClientHandler()); ServiceConnection mServiceConn = new ServiceConnection(){ @Override public void onServiceConnected(ComponentName name, IBinder service) { mServiceMessenger = new Messenger(service); Message msg = Message.obtain(null, MessengerService.MSG_TAG_REMOTE); msg.replyTo = mClientMessenger; try { mServiceMessenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { mServiceMessenger = null; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.one_textview); mTextView = (TextView) findViewById(R.id.content_show); bindService(new Intent(this, MessengerService.class), mServiceConn, BIND_AUTO_CREATE); } class ClientHandler extends Handler{ @Override public void handleMessage(Message msg) { switch (msg.what) { case MessengerService.MSG_TAG_CLIENT: if (mTextView != null) { mTextView.setText(msg.arg1+""); } break; default: super.handleMessage(msg); break; } } } }