Android Service那些不得不说的事-之二(Bound Service的实现方式)
To provide binding for service, you must implement the onBind() method. This method returns anIBinder object that defines the interface that clients can use to interact with the service.
三种不同的方式,说白了就是通过onBind()返回三种不同类型的IBinder object。
一、可以返回自定义的Binder(继承自Binder),并且在其中提供public methods that the client can call。
通常情况下,we returns the current Service instance, or an instance of another class hosted by the service with public methods theclient can call.
[html] view plaincopy
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
LocalService getService() {
// Return this instance of LocalService so clients can call public methods
return LocalService.this;
}
}
优点:
1. 使用简单,client在onServiceConnected()拿到Binder之后,可以直接cast到原本的类型,进行使用。
缺点:
1. 必须在同一个进程中使用,因为一般自定义的Binder不会按照IPC的要求实现Binder中的接口,如何支持IPC,请参看AIDL实现的Binder类。
注意:
1. 此种方法调用service的function时,就跟一个普通的函数调用一样,在当前线程执行,而不像IPC那样,service端的function都是在binder thread中执行。
三、使用AIDL,onBind()返回ServiceInterface.Stub mBinder = new ServiceInterface.Stub(){ }。
编译工具会根据.aidl文件生成一个.java文件,里面有AIDL实现的Binder类。例如,我们提供的.aild文件如下:
[html] view plaincopy
package com.baidu.test.aidl;
import com.baidu.test.aidl.ClientInterface;
interface ServiceInterface {
void register(ClientInterface client);
void serviceFun();
void invokeClientCallBack();
}
系统帮我们生成的.java文件如下:
[html] view plaincopy
package com.baidu.test.aidl;
public interface ServiceInterface extends android.os.IInterface {
public void register(com.baidu.test.aidl.ClientInterface client) throws android.os.RemoteException;
public void serviceFun() throws android.os.RemoteException;
public void invokeClientCallBack() throws android.os.RemoteException;
// ======================== Stub用在service端 ================================
public static abstract class Stub extends android.os.Binder implements com.baidu.test.aidl.ServiceInterface {
private static final java.lang.String DESCRIPTOR = "com.baidu.test.aidl.ServiceInterface";
static final int TRANSACTION_register = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_serviceFun = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_invokeClientCallBack = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
public Stub() {
// from Binder, Convenience method for associating a specific interface with the Binder.
// After calling, queryLocalInterface() will return the given owner IInterface
// when the corresponding descriptor is requested.
<span style="color:#FF0000;"><strong>this.attachInterface(this, DESCRIPTOR);</strong></span>
<pre name="code" class="html"> <span style="color:#FF0000;"><strong>private Messenger mService = null;</strong></span>
<strong><span style="color:#FF0000;">final Messenger mMessenger = new Messenger(new IncomingHandler());</span></strong>
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SERVICE_FUN_ALPHA:
break;
default:
super.handleMessage(msg);
}
}
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
<strong><span style="color:#FF0000;">mService = new Messenger(service);</span></strong>
try {
<span style="color:#FF0000;"><strong>Message msg = Message.obtain(null,MSG_REGISTER_CLIENT);</strong></span>
<strong><span style="color:#FF0000;">msg.replyTo = mMessenger;</span></strong> // 可选项,主要是用来向service注册client,从而实现双向IPC。
<span style="color:#FF0000;"><strong>mService.send(msg);</strong></span>
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void onServiceDisconnected(ComponentName className) {
mService = null;
}
}; </pre>
<p></p>
<p>优点:</p>
<p>1. 比较方便,而且可以实现进程间通信。<br>
</p>
<p>缺点:</p>
<p>1. 必须想办法将Message Id,在service和client之间共享。<br>
</p>
<p>注意:</p>
<p>1. 由于service是在main thread中创建,所以我们的Messager(包括构造Messager所需要提供的Handler)都是在main thread中创建的,所以一般情况下,service端的handleMessage()是在main thread中执行的。当然由于Handler创建时可以自定义所用的Looper,所以我们可以在service的onCreate()里面创建自己的线程,并prepare()线程自己的Looper,然后就可以让service端的handleMessage()运行在我们自己的线程中了。<br>
</p>
<p><br>
</p>
<br>