使用Messenger实现进程间通信(IPC)

来源:互联网 发布:满语翻译软件 编辑:程序博客网 时间:2024/05/16 09:35
    我们在使用远程服务时,需要进行进程间通信,可以通过实现AIDL接口。编写aidl文件也比较麻烦,有么有什么比较简单的方法呢?Android系统中提供了Messenger类,可直接实现客户端和服务端的交互。

代码示例

server端:

public class MyService extends Service {    Handler handler = new Handler() {    @Override    public void handleMessage(Message msg) {            Message reply = Message.obtain(msg);            switch (msg.what) {            case 100:                 reply.what = 100;                 try {                     Thread.sleep(2000);                     msg.replyTo.send(reply);                 } catch (InterruptedException e) {                     e.printStackTrace();                 } catch (RemoteException e) {                     e.printStackTrace();                 }                 break;            }            super.handleMessage(msg);        }    };private Messenger messenger = new Messenger(handler);    @Override    public IBinder onBind(Intent intent) {        return messenger.getBinder();    }}

    定义了一个Messenger对象,用Handler进行实例化,在OnBind中返回IBinder对象。不要忘了AndroidManifest文件中注册,

<service    android:name=".MyService"    android:enabled="true"    android:exported="true">    <intent-filter>        <action android:name="com.windy.serverclient.MyService"></action>        <category android:name="android.intent.category.DEFAULT" />    </intent-filter></service>
client端:
public class MainActivity extends AppCompatActivity {private Button btDownload;private TextView txtCon;private TextView download;private Messenger messenger;private boolean isConn;Handler handler = new Handler() {    @Override    public void handleMessage(Message msg) {        switch (msg.what) {            case 100:                download.setText("downloaded!");                break;         }         super.handleMessage(msg);     }};private Messenger replyMessenger = new Messenger(handler);private ServiceConnection mConn = new ServiceConnection() {    @Override    public void onServiceConnected(ComponentName name, IBinder service) {        messenger = new Messenger(service);        isConn = true;        txtCon.setText("server connected!");    }    @Override    public void onServiceDisconnected(ComponentName name) {        messenger = null;        isConn = false;        txtCon.setText("server disconnected!");    }};@Overrideprotected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        bindService();        txtCon = (TextView) findViewById(R.id.txtCon);        btDownload = (Button) findViewById(R.id.btDownload);        download = (TextView) findViewById(R.id.download);        btDownload.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                download.setText("downloading...");                try {                    Message msgToServer = Message.obtain(null, 100);                    msgToServer.replyTo = replyMessenger;                    if (isConn) {                        messenger.send(msgToServer);                    }                } catch (RemoteException e) {                    e.printStackTrace();                }            }        });}private void bindService() {        Intent intent = new Intent();        intent.setAction("com.windy.serverclient.MyService");        bindService(intent, mConn, Context.BIND_AUTO_CREATE);    }@Overrideprotected void onDestroy() {        super.onDestroy();        unbindService(mConn);    }}

先绑定服务bindService();
绑定成功后,根据返回的IBinder对象实例化Messenger;
通过Messenger的send方法将Message发送到服务端;
handler接收服务端返回的数据,更新。

布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <Button android:id="@+id/btDownload"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="download"/>    <TextView        android:id="@+id/txtCon"        android:layout_width="match_parent"        android:layout_height="wrap_content" />    <TextView         android:id="@+id/download"         android:layout_width="wrap_content"         android:layout_height="wrap_content" /></LinearLayout>

源码解析

    Messenger的构造函数,
public Messenger(Handler target) {    mTarget = target.getIMessenger();}public Messenger(IBinder target) {    mTarget = IMessenger.Stub.asInterface(target);}
    这两个构造函数在Demo中都有用到,目的都是为了实例化mTarget,
final IMessenger getIMessenger() {    synchronized (mQueue) {        if (mMessenger != null) {            return mMessenger;        }        mMessenger = new MessengerImpl();        return mMessenger;    }}private final class MessengerImpl extends IMessenger.Stub {    public void send(Message msg) {        msg.sendingUid = Binder.getCallingUid();        Handler.this.sendMessage(msg);    }}
    以Handler为参数的构造函数最终也是获得一个MessengerImpl对象,继承于IMessager.Stub,实现了send方法。

    消息如何发送呢?
/** * Send a Message to this Messenger's Handler. *  * @param message The Message to send.  Usually retrieved through * {@link Message#obtain() Message.obtain()}. *  * @throws RemoteException Throws DeadObjectException if the target * Handler no longer exists. */public void send(Message message) throws RemoteException {    mTarget.send(message);}
    从注释可以看出是将消息发送到实现该Messenger的Handler对象,最终执行handleMessage方法。并且建议我们使用obtain方法创建消息实例。
    mTarget是IMessager实例,而IMessenger是一个aidl文件,就是一个远程通信接口,其中定义了send方法,
package android.os;import android.os.Message;/** @hide */oneway interface IMessenger {    void send(in Message msg);}
    前面已看到MessengerImpl实现了send方法,其实最终就是通过Handler来发送消息。

0 0
原创粉丝点击