原文地址:http://www.android-doc.com/guide/components/bound-services.html
创建一个Bound服务
bound服务是 Service 类的一种实现,它允许其它应用程序与其绑定并交互。为了让服务支持绑定,你必须实现 onBind() 回调方法。这个方法返回一个 IBinder 对象,此对象定义了客户端与服务进行交互时所需的编程接口。
当你实现自己的bound服务时,最重要的工作就是定义 onBind() 回调方法所返回的接口。定义服务 IBinder 接口的方式有好几种。
创建一个支持绑定的服务时,你必须提供一个 IBinder ,用作客户端和服务间进行通信的编程接口。定义这类接口的方式有三种:
-
扩展Binder类
- 如果服务是你的应用程序所私有的,并且与客户端运行于同一个进程中(通常都是如此),你应该通过扩展 Binder类来创建你的接口,并从 onBind()返回一个它的实例。客户端接收该 Binder对象并用它来直接访问 Binder甚至 Service中可用的公共(public)方法。
- 如果你的服务只是为你自己的应用程序执行一些后台工作,那这就是首选的技术方案。不用这种方式来创建接口的理由只有一个,就是服务要被其它应用程序使用或者要跨多个进程使用。
-
使用Messenger
- 如果你需要接口跨越多个进程进行工作,可以通过 Messenger来为服务创建接口。在这种方式下,服务定义一个响应各类消息对象 Message的 Handler。此 Handler是 Messenger与客户端共享同一个 IBinder的基础,它使得客户端可以用消息对象 Message向服务发送指令。此外,客户端还可以定义自己的 Message,以便服务能够往回发送消息。
- 这是执行进程间通信(IPC)最为简便的方式,因为 Messenger 会把所有的请求放入一个独立进程中的队列,这样你就不一定非要把服务设计为线程安全的模式了。
-
使用AIDL
- Android接口定义语言AIDL(Android Interface Definition Language)完成以下的所有工作:将对象解析为操作系统可识别的原始形态,并将它们跨进程 序列化(marshal)以完成IPC。前一个使用 Messenger的方式,实际上也是基于AIDL的,它用AIDL作为底层结构。如上所述, Messenger将在一个单独的进程中创建一个包含了所有客户端请求的队列,这样服务每次就只会收到一个请求。可是,如果想让你的服务能同时处理多个请求,那你就可以直接使用AIDL。这种情况下,你的服务必须拥有多线程处理能力,并且是以线程安全的方式编写的。
- 要直接使用AIDL,你必须创建一个 .aidl文件,其中定义了编程的接口。Android SDK 工具使用此文件来生成一个抽象类(abstract class),其中实现了接口及对IPC的处理,然后你就可以在自己的服务中扩展该类。
注意: 绝大多数应用程序都不应该用AIDL来创建bound服务,因为这可能需要多线程处理能力并且会让代码变得更为复杂。 因此,AIDL对绝大多数应用程序都不适用,并且本文也不会讨论如何在服务中使用它的内容。如果你确信需要直接使用AIDL,那请参阅 AIDL 文档。
使用Messenger 的例子:
首先是服务端。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
public
class
MessengerTestService
extends
Service {
protected
static
final
String TAG =
"MessengerTestService"
;
private
Handler mHandler =
new
Handler() {
@Override
public
void
handleMessage(Message msg) {
switch
(msg.what) {
case
1
:
Log.d(TAG,
"收到消息"
);
//获取客户端message中的Messenger,用于回调
final
Messenger callback = msg.replyTo;
try
{
// 回调
callback.send(Message.obtain(
null
,
0
));
}
catch
(RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break
;
}
}
};
@Override
public
IBinder onBind(Intent intent) {
return
new
Messenger(mHandler).getBinder();
}
}
|
然后是客户端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
public
class
MainActivity
extends
Activity {
protected
static
final
String TAG =
"MainActivity"
;
Messenger messenger;
Messenger reply;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
reply =
new
Messenger(handler);
Intent intent =
new
Intent();
intent.setClassName(
"test.messenger"
,
"test.messenger.MessengerTestService"
);
// 绑定服务
bindService(intent,
new
ServiceConnection() {
@Override
public
void
onServiceDisconnected(ComponentName name) {
}
@Override
public
void
onServiceConnected(ComponentName name, IBinder service) {
Toast.makeText(MainActivity.
this
,
"bind success"
,
0
).show();
messenger =
new
Messenger(service);
}
}, Context.BIND_AUTO_CREATE);
}
public
void
sendMessage(View v) {
Message msg = Message.obtain(
null
,
1
);
// 设置回调用的Messenger
msg.replyTo = reply;
try
{
messenger.send(msg);
}
catch
(RemoteException e) {
e.printStackTrace();
}
}
private
Handler handler =
new
Handler() {
@Override
public
void
handleMessage(Message msg) {
Log.d(TAG,
"回调成功"
);
}
};
}
|