Bound Services

原文URL:Bound Services

(1)

Bound Services_第1张图片

Bound service在客户/服务器模式中充当服务端。一个Bound Service允许组件(比如Activities)绑定到该Service上,发送请求,接收响应,甚至是进行进程间通信(IPC)。一个Bound Service只存活在当它为其他的应用组件服务的时候,并且不会永远在后台运行下去。

Bound Services_第2张图片

本文档将向你展示如何创建一个Bound Service ,包括如何从其他的应用组件绑到到该Service。但是,你也应该参考一下Services文档中的关于Services的常识信息,例如,如何从一个Service提交Notifications,将Service 设置为前台运行等等。

(2)The Basics

Bound Services_第3张图片

Bound Service 是Service类的子类,它允许其他的应用程序绑定该Service,并和它进行交互。为了使一个Service 具有绑定功能,你必须实现onBind()回调方法。该方法返回一个IBinder对象,该对象定义了clients能用来与该Service 进行交互的编程接口。

Bound Services_第4张图片

 client 可以通过调用bindService()方法绑定该Service。当进行绑定时,必须提供一个ServiceConnection的实现,它用来监视与Service 的连接状态。bindService()方法会立即返回,并且没有返回值,但是,当Android 系统创建client与Service 之间的连接时,系统会调用ServiceConnection中的onServiceConnection()方法,把IBinder 对象交给client,这样的话,client可以使用该对象与Service 进行交互。


多个client可以同时连接该Service。但是,系统只会在第一个client绑定的时候调用你Service 的onBind()方法获取IBinder对象。然后系统会把这一个IBinder对象交给后续绑定到该Service的其他的client,而不会再调用onBind()方法。


当最后一个client解除与该Service 的绑定关系后,系统会销毁该Service (除非该Service 也是用startService()方法启动创建的)。

Bound Services_第5张图片

当你实现你的Bound Service 时,最重要的一点就是定义你的onBind()回调方法返回的IBinder  接口。有三种不同的方式可以定义你的Service 的IBinder 接口,下面将一一介绍各种方法。

(3)Creating a Bound Service


当创建一个具有绑定功能的Service 时,你必须提供一个IBinder 接口,它提供了client用来与该Service 交互的编程接口。你可以有三种方式定义此接口:


如果你的Service 只在你自己的应用中使用,并且和client运行在同一个进程中(这是一普遍的情况),你应该通过继承Binder类并从onBind()方法返回它的一个实例的方式创建该接口。client可以接收该Binder对象并使用它直接调用Binder实现类的或者甚至是Service 的public 方法。


如果你的Service 仅仅只是在你的自己应用程度中做一些后台工作,这是一种首选方式。你不能使用此种方式创建IBinder接口的唯一情况就是你的Service 要被其他的应用程序使用,或者跨跃不同的进程。

Bound Services_第6张图片

Bound Services_第7张图片



如果你的Service 只是在自己的应用程序中使用,并且不需要进行跨进程工作,那么你可以通过继承Binder 类来实现你的Binder 类,它可以使client能够直接调用Service 的public 方法。


注意:此种方式只适用于client和service在同一个应用程序和进程中,这是最普遍的情况。例如,XXX


下面是创建过程:

1》在你的Service中,创建一个Binder的实例:

1.1》这个Binder实例含有client要调用的public 方法

1.2》这个Binder实例返回当前的Service实例,该Service 含有client可以调用的public 方法(ps:下面的事例就是采用这种方法)

1.3》或者,XXX

2》从Service的onBind()方法中返回该Binder的实例

3》在client中,从onServiceConnected()回调方法接收此Binder对象实例并调用绑定的Service提供的方法


For example, here's a service that provides clients access to methods in the service through a Binder implementation:

package com.mytest.servicetest;

import java.util.Random;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

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) {
		// TODO Auto-generated method stub
		return mBinder;
	}

	/** method for clients */
	public int getRandomNumber() {
		return mGenerator.nextInt(100);
	}
}


LocalBinder提供了getService()方法,client通过此方法得到LocalService的实例。client可以通过该实例调用Service 中的public 方法。例如,client可以调用Service 中的getRandomNumber()方法。


下面是一个要绑定LocalService的Activity,并且在该Activity 中,当点击按钮时,调用LocalService 中的getRandomNumber()方法。

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


以上事例展示了client如何使用ServiceConnection实例以及onServiceConnected()回调方法绑定Service。下面详细介绍 一下绑定Service的过程。

Bound Services_第8张图片

应用程序组件(Clients)可以调用bindService()方法绑定一个service。然后Android 系统会调用service 的onBind()方法,该方法会返回一个IBinder对象,用来与service 进行交互。

绑定过程是异步的。也就是说,bindService()方法会立即返回并且不会向client返回IBinder对象。为了接收IBinder对象,client必须要创建一个ServiceConnection的实例,并把该实例传递给bindService()方法。ServiceConnection类包含一个回调方法(ps:也就是onServiceConnected()回调方法),Android系统就是用这个回调方法向client返回IBinder 对象的。

注意:只有activities,services和content providers可以绑定service--不可以用broadcast receiver绑定service


从client绑定service时,你必须:

1.实例化ServiceConnection.

实例时必须要重写 两个回调方法:

onServiceConnected()

Android系统会调用此方法将service中的onBind()方法返回的IBinder对象交给client.

onServiceDisconnected()

当client与service的连接忽然断开时,Android系统会调用此方法,比如当service突然崩溃时或者service被kill的时候。

但是,当client与service解除绑定时不会调用此方法。

2.client调用bindService()方法,并将实例化的ServiceConnection对象传递给它。

3.当Android系统调用onServiceConnected()方法时,你可以调用service中定义的接口方法。

4.调用unbindService()方法,解除与service 的绑定关系。

当client销毁时,client将解除与service的绑定关系,但是你应该总是在使用完service之后或者是当Activity暂停时解除绑定,这样的话,service 就可以在它没有被使用的时候停止了。(绑定与解除绑定的合适时机将在下面讨论。)


LocalService mService;
private ServiceConnection mConnection = new ServiceConnection() {
    // Called when the connection with the service is established
    public void onServiceConnected(ComponentName className, IBinder service) {
        // Because we have bound to an explicit
        // service that is running in our own process, we can
        // cast its IBinder to a concrete class and directly access it.
        LocalBinder binder = (LocalBinder) service;
        mService = binder.getService();
        mBound = true;
    }

    // Called when the connection with the service disconnects unexpectedly
    public void onServiceDisconnected(ComponentName className) {
        Log.e(TAG, "onServiceDisconnected");
        mBound = false;
    }
};


Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

Bound Services_第9张图片


Bound Services_第10张图片






你可能感兴趣的:(service,bound)