如果需要服务跟远程进程通信,那么就可以使用Messenger对象来给服务提供接口。这种技术允许你在不使用AIDL的情况下执行进程间通信(IPC)。

以下是信使(Messenger)对象的使用概要:

1.  服务端实现的一个处理器(Handler接口),这个处理器针对每次来自客户端的调用接收一次回调;

2.  这个处理器被用于创建一个信使对象(Messager)(这个信使对象要引用这个处理器);

3.  信使对象创建一个创建一个服务端从onBind()方法中返回给客户端的IBinder对象;

4.  客户端使用这个IBinder对象来实例化这个信使对象(信使引用了服务端的处理器),客户端使用这个信使给服务端发送Message对象;

5.  服务端在它的处理器(Handler)的handleMessage()方法中依次接收每个Message对象

在这种方法中,没有给客户端提供服务端的方法调用,相反,客户端会给发送服务端消息(Message)对象,服务端会在它的处理器中接受这些消息对象。

以下是使用Messenger接口的服务端示例代码:

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

注意看处理器(Handler)中的handleMessage()方法,这是服务接受输入Message对象和基于what成员属性判断做什么的地方。

客户端需要做的所有工作就是基于服务端返回的IBinder对象创建一个Messenger对象,并且使用这个Messenger对象的send()方法发送消息。如,以下是一个简单的Activity代码,它绑定服务,并且给服务发送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)对象,然后在客户端收到onServiceConnected()回调时,它给服务发送一个Message对象,这个对象在send()方法的参数的replyTo成员中包含了客户端的信使(Messenger)对象。

在以下代码示例中你能够看到客户端和服务端是如何进行双向通信的

MessageService.java(服务端):

/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.android.apis.app;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;

import java.util.ArrayList;

// Need the following import to get access to the app resources, since this
// class is in a sub-package.
import com.example.android.apis.R;
import com.example.android.apis.app.RemoteService.Controller;

/**
 * This is an example of implementing an application service that uses the
 * {@link Messenger} class for communicating with clients.  This allows for
 * remote interaction with a service, without needing to define an AIDL
 * interface.
 *
 * <p>Notice the use of the {@link NotificationManager} when interesting things
 * happen in the service.  This is generally how background services should
 * interact with the user, rather than doing something more disruptive such as
 * calling startActivity().
 */
public class MessengerService extends Service {
    /** For showing and hiding our notification. */
    NotificationManager mNM;
    /** Keeps track of all current registered clients. */
    ArrayList<Messenger> mClients = new ArrayList<Messenger>();
    /** Holds last value set by a client. */
    int mValue = 0;

/**
     * Command to the service to register a client, receiving callbacks
     * from the service.  The Message's replyTo field must be a Messenger of
     * the client where callbacks should be sent.
     */
    static final int MSG_REGISTER_CLIENT = 1;

/**
     * Command to the service to unregister a client, ot stop receiving callbacks
     * from the service.  The Message's replyTo field must be a Messenger of
     * the client as previously given with MSG_REGISTER_CLIENT.
     */
    static final int MSG_UNREGISTER_CLIENT = 2;

/**
     * Command to service to set a new value.  This can be sent to the
     * service to supply a new value, and will be sent by the service to
     * any registered clients with the new value.
     */
    static final int MSG_SET_VALUE = 3;

/**
     * Handler of incoming messages from clients.
     */
    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_REGISTER_CLIENT:
                    mClients.add(msg.replyTo);
                    break;
                case MSG_UNREGISTER_CLIENT:
                    mClients.remove(msg.replyTo);
                    break;
                case MSG_SET_VALUE:
                    mValue = msg.arg1;
                    for (int i=mClients.size()-1; i>=0; i--) {
                        try {
                            mClients.get(i).send(Message.obtain(null,
                                    MSG_SET_VALUE, mValue, 0));
                        } catch (RemoteException e) {
                            // The client is dead.  Remove it from the list;
                            // we are going through the list from back to front
                            // so this is safe to do inside the loop.
                            mClients.remove(i);
                        }
                    }
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

/**
     * Target we publish for clients to send messages to IncomingHandler.
     */
    final Messenger mMessenger = new Messenger(new IncomingHandler());

@Override
    public void onCreate() {
        mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);

// Display a notification about us starting.
        showNotification();
    }

@Override
    public void onDestroy() {
        // Cancel the persistent notification.
        mNM.cancel(R.string.remote_service_started);

// Tell the user we stopped.
        Toast.makeText(this, R.string.remote_service_stopped, Toast.LENGTH_SHORT).show();
    }

/**
     * When binding to the service, we return an interface to our messenger
     * for sending messages to the service.
     */
    @Override
    public IBinder onBind(Intent intent) {
        return mMessenger.getBinder();
    }

/**
     * Show a notification while this service is running.
     */
    private void showNotification() {
        // In this sample, we'll use the same text for the ticker and the expanded notification
        CharSequence text = getText(R.string.remote_service_started);

// Set the icon, scrolling text and timestamp
        Notification notification = new Notification(R.drawable.stat_sample, text,
                System.currentTimeMillis());

// The PendingIntent to launch our activity if the user selects this notification
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, Controller.class), 0);

// Set the info for the views that show in the notification panel.
        notification.setLatestEventInfo(this, getText(R.string.remote_service_label),
                       text, contentIntent);

// Send the notification.
        // We use a string id because it is a unique number.  We use it later to cancel.
        mNM.notify(R.string.remote_service_started, notification);
    }
}

MessengerServiceActivities.java(客户端):

package com.example.android.apis.app;

import com.example.android.apis.R;
import com.example.android.apis.app.LocalServiceActivities.Binding;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MessengerServiceActivities {
    /**
     * Example of binding and unbinding to the remote service.
     * This demonstrates the implementation of a service which the client will
     * bind to, interacting with it through an aidl interface.</p>
     *
     * <p>Note that this is implemented as an inner class only keep the sample
     * all together; typically this code would appear in some separate class.
     */
    public static class Binding extends Activity {
        /** Messenger for communicating with service. */
        Messenger mService = null;
        /** Flag indicating whether we have called bind on the service. */
        boolean mIsBound;
        /** Some text view we are using to show state information. */
        TextView mCallbackText;

/**
         * Handler of incoming messages from service.
         */
        class IncomingHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MessengerService.MSG_SET_VALUE:
                        mCallbackText.setText("Received from service: " + msg.arg1);
                        break;
                    default:
                        super.handleMessage(msg);
                }
            }
        }

/**
         * Target we publish for clients to send messages to IncomingHandler.
         */
        final Messenger mMessenger = new Messenger(new IncomingHandler());

/**
         * 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 service object we can use to
                // interact with the service.  We are communicating with our
                // service through an IDL interface, so get a client-side
                // representation of that from the raw service object.
                mService = new Messenger(service);
                mCallbackText.setText("Attached.");

// We want to monitor the service for as long as we are
                // connected to it.
                try {
                    Message msg = Message.obtain(null,
                            MessengerService.MSG_REGISTER_CLIENT);
                    msg.replyTo = mMessenger;
                    mService.send(msg);

// Give it some value as an example.
                    msg = Message.obtain(null,
                            MessengerService.MSG_SET_VALUE, this.hashCode(), 0);
                    mService.send(msg);
                } catch (RemoteException e) {
                    // In this case the service has crashed before we could even
                    // do anything with it; we can count on soon being
                    // disconnected (and then reconnected if it can be restarted)
                    // so there is no need to do anything here.
                }

// As part of the sample, tell the user what happened.
                Toast.makeText(Binding.this, R.string.remote_service_connected,
                        Toast.LENGTH_SHORT).show();
            }

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;
                mCallbackText.setText("Disconnected.");

// As part of the sample, tell the user what happened.
                Toast.makeText(Binding.this, R.string.remote_service_disconnected,
                        Toast.LENGTH_SHORT).show();
            }
        };

void doBindService() {
            // Establish a connection with the service.  We use an explicit
            // class name because there is no reason to be able to let other
            // applications replace our component.
            bindService(new Intent(Binding.this,
                    MessengerService.class), mConnection, Context.BIND_AUTO_CREATE);
            mIsBound = true;
            mCallbackText.setText("Binding.");
        }

void doUnbindService() {
            if (mIsBound) {
                // If we have received the service, and hence registered with
                // it, then now is the time to unregister.
                if (mService != null) {
                    try {
                        Message msg = Message.obtain(null,
                                MessengerService.MSG_UNREGISTER_CLIENT);
                        msg.replyTo = mMessenger;
                        mService.send(msg);
                    } catch (RemoteException e) {
                        // There is nothing special we need to do if the service
                        // has crashed.
                    }
                }

// Detach our existing connection.
                unbindService(mConnection);
                mIsBound = false;
                mCallbackText.setText("Unbinding.");
            }
        }

/**
         * Standard initialization of this activity.  Set up the UI, then wait
         * for the user to poke it before doing anything.
         */
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

setContentView(R.layout.messenger_service_binding);

// Watch for button clicks.
            Button button = (Button)findViewById(R.id.bind);
            button.setOnClickListener(mBindListener);
            button = (Button)findViewById(R.id.unbind);
            button.setOnClickListener(mUnbindListener);

mCallbackText = (TextView)findViewById(R.id.callback);
            mCallbackText.setText("Not attached.");
        }

private OnClickListener mBindListener = new OnClickListener() {
            public void onClick(View v) {
                doBindService();
            }
        };

private OnClickListener mUnbindListener = new OnClickListener() {
            public void onClick(View v) {
                doUnbindService();
            }
        };
    }
}

Android 绑定类型服务---使用信使(Messenger)相关推荐

  1. java 信使服务_Android 绑定类型服务---使用信使(Messenger)

    如果需要服务跟远程进程通信,那么就可以使用Messenger对象来给服务提供接口.这种技术允许你在不使用AIDL的情况下执行进程间通信(IPC). 以下是信使(Messenger)对象的使用概要: 1 ...

  2. Android服务之信使

    所谓的信使就是Messenger,它的作用是建立不同应用之间客户端和服务端的连接,并进而实现信息的传递. 对于服务端信使的创建: ①创建一个Handler对象handler ②创建一个信使对象Mess ...

  3. Android 绑定服务 bindService

    绑定服务是客户端--服务器接口中的服务器.组件(如activity)和服务进行绑定后,可以发送请求.接收响应.执行进程间通信(IPC).不会无限期在后台运行. 要提供服务绑定,必须实现onBind() ...

  4. android 绑定服务 解绑服务,安卓案例:绑定和解绑服务

    安卓案例:绑定和解绑服务 一.运行效果 二.实现步骤 1.创建安卓应用BindUnbindService 2.准备背景图片background.jpg,放到mipmap目录里 3.布局资源文件acti ...

  5. java 信使服务_1.简单化-信使messenger+集合型参数(collecting parameter)

    1.简单化-信使messenger+集合型参数(collecting parameter) ? ? 以下就开始我们的设计模式之旅吧!其实这里我说一下题外话先,为什么我要写博客,其实写博客这个我很久就想 ...

  6. android四大组件 服务,Android四大组件之Service

    Service Service(服务)是一个可以在后台执行长时间运行操作而不使用用户界面的应用组件.服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行. 此外,组件可以绑定到 ...

  7. 信使 Messenger

    信使 Messenger: 1.服务端需要绑定服务让客户端访问 Messenger sMessenger=new Messenger(new Handler(){ }); public IBind o ...

  8. Android绑定多个aidl,android aidl 多`module`版的实现

    多module版,pojo类型数据的双向传递 [service client] android中如何进行跨进程通信的? aidl是什么? android中如何通过aidl实现跨进程通信? 最简单的ai ...

  9. android创建标题栏,【Android】利用服务Service创建标题栏通知

    创建标题栏通知的核心代码 public void CreateInform() { //定义一个PendingIntent,当用户点击通知时,跳转到某个Activity(也可以发送广播等) Inten ...

最新文章

  1. 31 多线程同步之Lock(互斥锁)
  2. python常见错误-新手常见Python错误及异常解决处理方案
  3. twiiq开发随笔(2)
  4. 卓越性能代码_编程语言性能实测,Go比Python更胜一筹?
  5. 如何添加团队成员,并为团队成员分配访问权限(转载)
  6. Android 动画(二)
  7. OpenShift Security (7) - 风险合规评估
  8. 基于OpenCV的计算机视觉入门(5)图像美化(上)
  9. 遍历查询+从非根节点开始遍历+从下向上遍历树+从层次化查询中删除节点和分支...
  10. 1900型USB接口扫描枪设置虚拟串口模式提升扫描速度
  11. meanshift算法学习(二):opencv中的meanshift
  12. android 获得屏幕方向,Android 获取设置屏幕横竖屏
  13. 金海佳学C++primer 练习9.47
  14. Android测试能不能用monk,Android自动化测试-Monkey和MonkeyRunner
  15. 迎难而上 数据库管理员怎样走向成功?(转)
  16. Linux 之 del_timer 和 del_timer_sync
  17. android常用两种适配器,Android常见设计模式五:适配器模式
  18. 突然发现刷朋友圈是最孤独
  19. Java 技术路上的迷茫及远方
  20. dspace rcp_RCP工具箱开源

热门文章

  1. DCOM EXCE权限配置问题
  2. django博客项目7
  3. 链接详解--共享库命名
  4. hdu 1514 记忆化搜索
  5. js:语言精髓笔记12--动态语言特性(2)
  6. 多个html网页共享变量,多个jsp页面共享一个js对象的超级方法
  7. python中loop的用法_python-在Tensorflow中使用tf.while_loop更新变量
  8. 简历准备及面试技巧,你应该知道的一切
  9. 学妹惊呼:使用Java8改造后的模板方法模式真的是yyds
  10. RocketMQ基础概念剖析源码解析