zoukankan      html  css  js  c++  java
  • Messenger实现Android IPC

    当Service不需要支持并发操作时Messenger会非常有用。Messenger类使用Handler执行每个传入的消息,所有客户端的调用都按顺序运行在同一个线程上,这和AIDL是有区别的,AIDL每个客户端对应一个线程。使用Messenger类还能避免AIDL文件带来的问题,并可以方便地为客户端提供异步消息API。虽然没有那么强大,但该类有时候会很有效,因为它更容易在客户端和Service实现。

    下面的例子展示了如何使用Messenger类来提供异步API。首先在onCreate()方法中创建Messenger,然后在onBind()方法中返回Binder对象。当Messenger接受到消息时,它使用存储在replyTo成员变量里的Messenger对象响应客户端的请求。

    public class MessengerService extends Service {
        private Handler mMessageHandler;
    private Messenger mMessenger;
    public MessengerService() {
        }
    
        @Override
    public IBinder onBind(Intent intent) {
            return this.mMessenger.getBinder();
    }
    
        @Override
    public void onCreate() {
            super.onCreate();
    HandlerThread handlerThread=new HandlerThread("MessengerService");
    handlerThread.start();
    this.mMessageHandler=new Handler(handlerThread.getLooper(),new MyhandlerCallback());
    this.mMessenger=new Messenger(this.mMessageHandler);
    }
    
        @Override
    public void onDestroy() {
            super.onDestroy();
    this.mMessageHandler.getLooper().quit();
    }
    
        private class MyhandlerCallback implements Handler.Callback{
            @Override
    public boolean handleMessage(Message msg) {
                boolean delivered=false;
    switch (msg.what){
                    case 0:
    //执行具体的任务
                        delivered=true;
    break;
    case 1:
    //执行具体的任务
                        break;
    }
                Message reply=Message.obtain(null,2);//生成消息
    try {
                    msg.replyTo.send(reply);//反馈给客户端
    } catch (RemoteException e) {
                    e.printStackTrace();
    }
                return true;
    }
        }
    }
       服务器端配置文件代码如下:<service
    android:name=".MessengerService"
    android:enabled="true"
    android:exported="true" >
            <intent-filter>
                <action android:name="com.example.liyuanjing.myapplication.MESSENGER_SERVICE"/>
            </intent-filter>
        </service>
    

    下例中,客户端首先绑定到Service,然后使用IBinder作为参数构建一个Messenger对象,作为运行在远程Service中的Messenager的代理。当向Service发送消息时,也可以设置Message对象的replyTo属性。

    public class MainActivity extends Activity implements ServiceConnection {
        private Button start;
    private Messenger mRemoteMessenger;
    private Messenger mReplyMessenger;
    private Handler mReplyHandler;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    this.start=(Button)findViewById(R.id.start);
    HandlerThread handlerThread=new HandlerThread("ReplyMessenger");
    handlerThread.start();
    this.mReplyHandler=new Handler(handlerThread.getLooper(),new ReplyHandlerCallback());
    this.mReplyMessenger=new Messenger(this.mReplyHandler);
    }
    
        @Override
    protected void onResume() {
            super.onResume();
    bindService(new Intent("com.example.liyuanjing.myapplication.MESSENGER_SERVICE"),this,BIND_AUTO_CREATE);
    }
    
        @Override
    protected void onPause() {
            super.onPause();
    unbindService(this);
    }
    
        @Override
    protected void onDestroy() {
            super.onDestroy();
    this.mReplyHandler.getLooper().quit();
    }
    
        public void onSendTextPressed(View v){
            Message message=Message.obtain();
    message.what=0;
    Bundle bundle=new Bundle();
    bundle.putInt("key",1);
    message.obj=bundle;
    message.replyTo=mReplyMessenger;
    try {
                mRemoteMessenger.send(message);
    } catch (RemoteException e) {
                e.printStackTrace();
    }
        }
    
        @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
            this.mRemoteMessenger=new Messenger(service);
    this.start.setOnClickListener(new View.OnClickListener() {
                @Override
    public void onClick(View v) {
                    onSendTextPressed(v);
    }
            });
    }
    
        @Override
    public void onServiceDisconnected(ComponentName name) {
            this.mRemoteMessenger=null;
    }
        private class ReplyHandlerCallback implements Handler.Callback{
            @Override
    public boolean handleMessage(Message msg) {
                switch (msg.what){
                    case 2:
                        Toast.makeText(MainActivity.this,"接受到了",Toast.LENGTH_LONG).show();
    break;
    }
                return true;
    }
        }
    }
    

       注意必须用Bundle传递常规类型数据,否则会报错:

    java.lang.RuntimeException: Can't marshal non-Parcelable objects across processes.

    因为Binder事务传递的数据被称为包裹(Parcel),必须实现Parcelable接口,否则无法在两个应用之间进行通信。之所以用Bundle传递是因为该类实现了Parcelable接口。当然如果要传递类也必须实现该接口。

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    php包含(include/require)文件时的作用域
    Android使用DrawerLayout仿qq6.6版本侧滑效果
    Android几种强大的下拉刷新库
    Android 捕捉app系统中未处理的异常
    Android中内存泄露与如何有效避免OOM总结
    Android进程间的通信之Messenger
    Android中Parcelable接口用法
    《完美解决系列》Android5.0以上 Implicit intents with startService are not safe
    Android高效加载大图、多图解决方案,有效避免程序OOM
    使用真机导致Androidstudio打印不出log
  • 原文地址:https://www.cnblogs.com/liyuanjinglyj/p/4656572.html
Copyright © 2011-2022 走看看