使用 Messenger实现与独立进程的Service的双向通信

1、先对比一下,咱们要知道什么时候使用Messenger更合适,下面是官网给出的解释。

Messenger 与 AIDL 比较 

当您需要执行 IPC 时,为您的接口使用 Messenger 要比使用 AIDL 实现它更加简单,因为 Messenger 会将所有服务调用排入队列,而纯粹的 AIDL 接口会同时向服务发送多个请求,服务随后必须应对多线程处理。

对于大多数应用,服务不需要执行多线程处理,因此使用 Messenger 可让服务一次处理一个调用。如果您的服务必须执行多线程处理,则应使用 AIDL 来定义接口。

 

2、创建一个独立进程的服务

public class MyService extends Service {


    static final int MSG_SAY_HELLO = 1;

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

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
        return mMessenger.getBinder();
    }

}
IncomingHandler用来接受我们从客户端传递过来的消息 
mMessenger可以看作一个承载Handler可以跨进程的信使

别忘了独立进程的服务需要加process

        <service android:name=".MyService"
            android:exported="false"
            android:process=":myService"
            ></service>

3、客户端链接服务端

客户端只需根据服务返回的 IBinder 创建一个 Messenger,然后利用 Messenger send()方法发送消息

public class MainActivity extends AppCompatActivity {

    final String TAG = getClass().getSimpleName();

    Messenger mService = null;
    boolean mBound;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }


    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = new Messenger(service);

            mBound = true;
           
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            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, MyService.MSG_SAY_HELLO, 0, 0);
        try {
            mService.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }



    @Override
    protected void onStart() {
        super.onStart();
        bindService(new Intent(this,MyService.class),mConnection,Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }
}

这样就实现了与服务端的链接和给服务端发送消息的实例。

4、实现服务端回传数据给客户端

实现方式其实是很简单,同样用Messenger。首先在客户端创建一个Handler和Messenger,在服务链接成功后onServiceConnected方法里通过Message的replyTo方法赋值 使用服务端的Messenger的send方法回传回去。

public class MainActivity extends AppCompatActivity {

    final String TAG = getClass().getSimpleName();

    Messenger mService = null;
    boolean mBound;


    static final int MSG_RESULT_CODE = 1;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_RESULT_CODE:
                    msg.getData().setClassLoader(Book.class.getClassLoader());
                    Book book = msg.getData().getParcelable("book");
                    
                    Toast.makeText(MainActivity.this,""+ book.toString(),Toast.LENGTH_SHORT).show();
                    break;
                    default:
                        super.handleMessage(msg);
            }
        }
    };

    final Messenger mMessenger = new Messenger(mHandler);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }


    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = new Messenger(service);

            mBound = true;

            Message message = new Message();
            message.replyTo = mMessenger;
            message.what = MyService.MSG_REQUEST_MESSAGE;
            try {
                mService.send(message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mService = null;
            mBound = false;
        }
    };
.........
}
public class Book implements Parcelable {

    String name;
    int price;

    public Book() {}


    protected Book(Parcel in) {
        writeToParcel(in);
    }

    public void writeToParcel(Parcel in) {
        name = in.readString();
        price = in.readInt();
    }

    public static final Creator<Book> CREATOR = new Creator<Book>() {
        @Override
        public Book createFromParcel(Parcel in) {
            return new Book(in);
        }

        @Override
        public Book[] newArray(int size) {
            return new Book[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(price);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}

注意:在使用Messenger进行跨进程通信时,传递非基本类型和系统类型需要实现Parcelable接口,并且在取数据前Bundle要

setClassLoader,具体请看https://blog.csdn.net/dongbaoming/article/details/54312824

5、服务端接受客户端的Messenger,并使用客户端的Messenger回传数据

public class MyService extends Service {


    static final int MSG_SAY_HELLO = 1;
    static final int MSG_REQUEST_MESSAGE = 2;


    private Messenger mRequestMessenger = null;

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

                    Book book = new Book();
                    book.setName("Java 编程思想");
                    book.setPrice(66);

                    Message message = new Message();
                    message.what = MainActivity.MSG_RESULT_CODE;
                    message.getData().putParcelable("book",book);

                    try {
                        mRequestMessenger.send(message);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }

                    break;
                case MSG_REQUEST_MESSAGE:
                    mRequestMessenger = msg.replyTo;
                    break;
                default:
                    super.handleMessage(msg);
            }

        }
    }

.......................

}

简单的跨进程Service通信已经完成了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值