Android学习笔记18——Bound Services

         一个Bound Service在客户端和服务器接口中是一个服务器。Bound Service允许组件绑定到这个Service,发送请求,接受响应,甚至表现出进程间通信。Bound Service仅仅当它服务于另一个应用程序组件时才会存活,并且不能独立的运行在后台。

        Bound Service是一个Service类的实现,允许其他应用程序绑定他并且和他进行交互。为了绑定一个Service,你必须实现onBind回调方法,这个方法返回一个IBind对象,这个IBind对象定义了客户端和服务器交互的程序接口。

        一个客户端能够调用bindService方法绑定到Service,当它连接的时候,它必须提供一个ServiceConnection的实现,它控制着与这个Service的连接。这个bindService方法不会返回任何值,但是当系统创建客户端与服务器的连接时,它会调用ServiceConnecte类的onServiceConnected()方法,客户端能够用IBinder和这个Service通讯。

         在同一时间,可以有多个客户端连接到这个Service,然而仅仅当第一个客户端和这个Service绑定的时候系统才会调用Service的onBind方法获取IBind对象。系统将会发送同样的IBind到其他要绑定这个Service的客户端,而不是再次调用oBind方法。

        当最后一个客户端和这个Service解除绑定的时候,系统就会销毁这个Service。

        当我们实现我们的Bound Service的时候,最重要的部分是定义我们Service的onBind回调方法返回的接口。我们可以有一下三种方式来定义这个接口。

 第一、继承Binder这个类

         如果我们的Service是对于我们的应用程序是私有的并且和客户端运行在同一个进程中,我们应该继承Binder这个类来创建我们的接口,并且从onBind方法中返回一个Binder的实例。当我们要为我们的应用程序创建一个后台的工作时,这种做法是一种比较好的做法。

第二、使用一个Messager

         如果我们希望我们的接口能够跨进行进行工作,我们可以用Messager来为我们的Service创建一个接口。用这种方法,我们定义一个Handler去响应不同类型的Messager对象。这个Hanlder是一个Messager对象和一个客户端分享IBinder的基础,运行客户端用Messager对象发送命令给这个Service。另外,客户端也可以定义自己的Messgaer对象,因此这个Service也能够发送Messager给客户端。

第三、使用AIDL

        AIDL(Android Interface Define Language)所做的工作是把对象分解成操作系统能够识别的原生的语言,并且安排他们跨进程进行进程间的通讯。以上所说的Messager技术,就是基于AIDL。正如前面所提到过的,Messager对象创建了在线程中为所有客户端请求创建一个请求队列,因此这个Service一次仅能接收一个请求。然而,如果我们想要我们的Service能够一次接受多个请求,我们可以直接使用AIDL,在这种情况下,你的Service必须能够胜任多线程并且实现安全的。

    我们为了使用AIDL,我们需要定义一个.aidl文件,这个文件定义了程序的接口。Android SDK工具用这个文件生成了一个抽象类,这个抽象类定义了定义了接口和操作IPC的实现,在我们的Service中我们可以继承这个抽象类。

注意:大多数情况下,我们一般来说不会使用AIDL来创建一个Bound Service,因为它可能需要一个多线程的兼容并且导致一个更加复杂的实现。正因为如此,AIDL不太适合大多数的应用程序,所以我们不会在这里进行讲解关于AIDL的用法。

继承Binder类的讲解

如果我们的Service仅仅需要在我们自己的应用程序中使用并且不需要跨进程工作,那么我们可以通过继承Binder来实现我们自己的Binder,这个Binder可以让客户端直接访问我们的Service。

注意,这种方法仅仅适用于客户端和服务端在同一个应用程序和进程中,例如,一个音乐播放应用程序需要把一个Activty和一个在后台播放音乐的Service进行绑定的时候,这种方式将会是一个很好做法。

1、首先,在我们的Service中我们可以创建一个IBinder的实例通过一下几种方式

      1>包含这个客户端能够访问的公共方法;

      2>返回当前Service的实例,这个实例中的公共方法客户端可以访问;

      3>或者,返回被这个Service主导的另一个类的实例,这个实例包含了可以被客户端访问的公共方法;

2、从onBinder这个回调方法中返回Binder的实例;

3、在客户端中接受到来自onServiceConnected()回调方法;

public class LocalService extends Service {
    // Binder given to clients
    private final IBinder mBinder = new LocalBinder();
    // Random number generator
    private final Random mGenerator = new Random();

    /**
     * Class used for the client Binder.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with IPC.
     */
    public class LocalBinder extends Binder {
        LocalService getService() {
            // Return this instance of LocalService so clients can call public methods
            return LocalService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    /** method for clients */
    public int getRandomNumber() {
      return mGenerator.nextInt(100);
    }
}
public class BindingActivity extends Activity {
    LocalService mService;
    boolean mBound = false;

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

    @Override
    protected void onStart() {
        super.onStart();
        // Bind to LocalService
        Intent intent = new Intent(this, LocalService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        // Unbind from the service
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }

    /** Called when a button is clicked (the button in the layout file attaches to
      * this method with the android:onClick attribute) */
    public void onButtonClick(View v) {
        if (mBound) {
            // Call a method from the LocalService.
            // However, if this call were something that might hang, then this request should
            // occur in a separate thread to avoid slowing down the activity performance.
            int num = mService.getRandomNumber();
            Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
        }
    }

    /** Defines callbacks for service binding, passed to bindService() */
    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className,
                IBinder service) {
            // We've bound to LocalService, cast the IBinder and get LocalService instance
            LocalBinder binder = (LocalBinder) service;
            mService = binder.getService();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };
}

使用Messager对象

如果我们想要和远程的Service进行通讯,你能使用Messager对象来来为你的Service提供接口。这种技术允许你不必通过AIDL来表现进程间通讯。

下面是一些如何使用Messager对象的总结:

1、Service实现一个Handler,这个Handler接收每一个来自客户端请求的回调;

2、这个Handler被用来创造一个Messager对象;

3、而这个Meeager对象创建一个IBinder对象,这个Binder对象从这个Service的onBind()方法中返回到客户端;

4、客户端用这个IBinder实例化这个Messager,客户端用这个IBinder给这个Service发送一个Messager对象;

5、这个Service在它的Handler对象的handleMessage()方法中接收没一个请求。

<span style="font-size:12px;">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();
    }
}</span>
<span style="font-size:12px;">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;
        }
    }
}</span>


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值