您的位置:首页 > 移动开发 > Android开发

android service 学习(上)

2011-10-26 14:58 441 查看
Service是android系统中的一种组件,它跟Activity的级别差不多,但是他不能自己运行,只能后台运行,并且可以和其他组件进行交互。Service的启动有两种方式:context.startService()和context.bindService()。

使用context.startService()启动Service是会会经历:
context.startService()->onCreate()->onStart()->Servicerunning
context.stopService()|->onDestroy()->Servicestop

如果Service还没有运行,则android先调用onCreate()然后调用onStart();如果Service已经运行,则只调用onStart(),所以一个Service的onStart方法可能会重复调用多次。

stopService的时候直接onDestroy,如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行。该Service的调用者再启动起来后可以通过stopService关闭Service。

所以调用startService的生命周期为:onCreate-->onStart(可多次调用)-->onDestroy

使用使用context.bindService()启动Service会经历:
context.bindService()->onCreate()->onBind()->Servicerunning
onUnbind()->onDestroy()->Servicestop

onBind
将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。这个时候把调用者
(Context,例如Activity)会和Service绑定在一起,Context退出了,Srevice就会调用
onUnbind->onDestroy相应退出。

所以调用bindService的生命周期为:onCreate-->onBind(只一次,不可多次绑定)-->onUnbind-->onDestory。

在Service每一次的开启关闭过程中,只有onStart可被多次调用(通过多次startService调用),其他onCreate,onBind,onUnbind,onDestory在一个生命周期中只能被调用一次。

service可以在和多场合的应用中使用,比如播放多媒体的时候用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD卡上文件的变化,再或者在后台记录你地理信息位置的改变等等,总之服务嘛,总是藏在后头的。

下面我做了一个简单的音乐播放的应用,分别使用startService和bindService来启动本地的服务。
而在下一篇《androidservice学习(下)》会介绍通过AIDL对Service进行远程调用。

下面是整个应用启动界面:


先从使用startService启动Service学起

首先编写一个Activity

01
public
class
PlayMusic
extends
Activity
implements
OnClickListener{
02
private
static
final
StringTAG=
"PlayMusic"
;
03
private
ButtonplayBtn;
04
private
ButtonstopBtn;
05
private
ButtonpauseBtn;
06
private
ButtonexitBtn;
07
private
ButtoncloseBtn;
08
09
//....(详见源码)
10
11
@Override
12
public
void
onClick(Viewv){
13
int
op=-
1
;
14
Intentintent=
new
Intent(
"org.allin.android.musicService"
);
15
16
//广播用
17
//Intentintent=newIntent("org.allin.android.musicReceiver");
18
19
switch
(v.getId()){
20
case
R.id.play:
21
Log.d(TAG,
"onClick:playingmuic"
);
22
op=
1
;
23
break
;
24
case
R.id.stop:
25
Log.d(TAG,
"onClick:stopingmusic"
);
26
op=
2
;
27
break
;
28
case
R.id.pause:
29
Log.d(TAG,
"onClick:pausingmusic"
);
30
op=
3
;
31
break
;
32
case
R.id.close:
33
Log.d(TAG,
"onClick:close"
);
34
this
.finish();
35
break
;
36
case
R.id.exit:
37
Log.d(TAG,
"onClick:exit"
);
38
op=
4
;
39
stopService(intent);
40
this
.finish();
41
break
;
42
}
43
44
Bundlebundle=
new
Bundle();
45
bundle.putInt(
"op"
,op);
46
intent.putExtras(bundle);
47
startService(intent);
48
49
//sendBroadcast(intent);
50
}
51
52
53
}
通过重写onClick方法来实现对播放音乐的控制。这里把播放音乐的各种操作用数字的方式通过Intent传递给service。
构造一个Intent,ntentintent=newIntent("org.allin.android.musicService");
"org.allin.android.musicService"是在AndroidManifest.xml文件中对service类的定义

1
<serviceandroid:enabled=
"true"
android:name=
".MusicService"
>
2
<intent-filter>
3
<actionandroid:name=
"org.allin.android.musicService"
/>
4
</intent-filter>
5
</service>
把操作码放在Bundle中
Bundlebundle=newBundle();
bundle.putInt("op",op);
intent.putExtras(bundle);
最后使用startService(intent);启动服务。
下面看看Service是怎么实现的。

MusicService.java

01
/**
02
*@authorallin.dev
03
*http://allin.cnblogs.com/
04
*
05
*/
06
public
class
MusicService
extends
Service{
07
08
private
static
final
StringTAG=
"MyService"
;
09
private
MediaPlayermediaPlayer;
10
11
/*
12
*(non-Javadoc)
13
*
14
*@seeandroid.app.Service#onBind(android.content.Intent)
15
*/
16
@Override
17
public
IBinderonBind(Intentarg0){
18
return
null
;
19
}
20
21
@Override
22
public
void
onCreate(){
23
Log.v(TAG,
"onCreate"
);
24
if
(mediaPlayer==
null
){
25
mediaPlayer=MediaPlayer.create(
this
,R.raw.tmp);
26
mediaPlayer.setLooping(
false
);
27
}
28
}
29
30
@Override
31
public
void
onDestroy(){
32
Log.v(TAG,
"onDestroy"
);
33
if
(mediaPlayer!=
null
){
34
mediaPlayer.stop();
35
mediaPlayer.release();
36
}
37
}
38
39
@Override
40
public
void
onStart(Intentintent,
int
startId){
41
Log.v(TAG,
"onStart"
);
42
if
(intent!=
null
){
43
Bundlebundle=intent.getExtras();
44
if
(bundle!=
null
){
45
46
int
op=bundle.getInt(
"op"
);
47
switch
(op){
48
case
1
:
49
play();
50
break
;
51
case
2
:
52
stop();
53
break
;
54
case
3
:
55
pause();
56
break
;
57
}
58
59
}
60
}
61
62
}
63
64
public
void
play(){
65
if
(!mediaPlayer.isPlaying()){
66
mediaPlayer.start();
67
}
68
}
69
70
public
void
pause(){
71
if
(mediaPlayer!=
null
&&mediaPlayer.isPlaying()){
72
mediaPlayer.pause();
73
}
74
}
75
76
public
void
stop(){
77
if
(mediaPlayer!=
null
){
78
mediaPlayer.stop();
79
try
{
80
//在调用stop后如果需要再次通过start进行播放,需要之前调用prepare函数
81
mediaPlayer.prepare();
82
}
catch
(IOExceptionex){
83
ex.printStackTrace();
84
}
85
}
86
}
87
88
}
服务使用了系统自带MediaPlayer进行音乐的播放控制。当调用了startService后服务会先调用onCreate,我们在里面对MediaPlayer进行初始化。接着会调用onStart,可以看到传递给startService()的Intent对象会传递给onStart()方法,这样我们就可以得到intent里面的操作码:
Iundlebundle=intent.getExtras();
intop=bundle.getInt("op");
然后更具定义好的操作码进行相应的f播放操作。启动后界面如下图:



图中的”close”和“exit”是不同的,close只是调用finish()退出当前的Activity,但是Service并没有关掉,音乐会继续播放。而exit就是调用了stopService(intent);来停止服务,Service会调用onDestroy()方法来对mediaPlayer进行停止和释放资源。

有时候如果服务只提供一些操作接口,我们也可以通过广播的g方式来启动服务。
首先要定义一个Receiver,并继承BroadcastReceiver,然后在AndroidManifest.xml中进行注册:

1
<receiverandroid:name=
".MusicReceiver"
>
2
<intent-filter>
3
<actionandroid:name=
"org.allin.android.musicReceiver"
/>
4
</intent-filter>
5
</receiver>
Receiver的实现:

MusicReceiver.java

01
/**
02
*@authorallin.dev
03
*http://allin.cnblogs.com/
04
*
05
*/
06
public
class
MusicReceiver
extends
BroadcastReceiver{
07
08
private
static
final
StringTAG=
"MusicReceiver"
;
09
@Override
10
public
void
onReceive(Contextcontext,Intentintent){
11
Log.d(TAG,
"onReceive"
);
12
Intentit=
new
Intent(
"org.allin.android.musicService"
);
13
Bundlebundle=intent.getExtras();
14
it.putExtras(bundle);
15
16
if
(bundle!=
null
){
17
int
op=bundle.getInt(
"op"
);
18
if
(op==
4
){
19
context.stopService(it);
20
}
else
{
21
context.startService(it);
22
}
23
}
24
25
}
26
27
}
然后对PlayMusic中的onclick方法进行些改造,把Intent指向Receiver
Intentintent=newIntent("org.allin.android.musicReceiver");
intent中绑定的操作码都不变,再调用sendBroadcast(intent);把intentg广播出去。
当MusicReceiver接受到广播后根据操作码进行相应的操作。

接下来的例子就是使用bindService来启动Service
首先一样是写一个Activity

01
public
class
PlayBindMusic
extends
Activity
implements
OnClickListener{
02
03
private
static
final
StringTAG=
"PlayBindMusic"
;
04
private
ButtonplayBtn;
05
private
ButtonstopBtn;
06
private
ButtonpauseBtn;
07
private
ButtonexitBtn;
08
09
private
BindMusicServicemusicService;
10
11
@Override
12
public
void
onClick(Viewv){
13
14
switch
(v.getId()){
15
case
R.id.play:
16
Log.d(TAG,
"onClick:bindingsrvice"
);
17
musicService.play();
18
break
;
19
case
R.id.stop:
20
Log.d(TAG,
"onClick:stopingsrvice"
);
21
if
(musicService!=
null
){
22
musicService.stop();
23
}
24
break
;
25
case
R.id.pause:
26
Log.d(TAG,
"onClick:pausingsrvice"
);
27
if
(musicService!=
null
){
28
musicService.pause();
29
}
30
break
;
31
case
R.id.exit:
32
Log.d(TAG,
"onClick:exit"
);
33
this
.finish();
34
break
;
35
}
36
}
37
38
39
private
void
connection(){
40
Log.d(TAG,
"connecting....."
);
41
Intentintent=
new
Intent(
"org.allin.android.bindService"
);
42
bindService(intent,sc,Context.BIND_AUTO_CREATE);
43
44
}
45
private
ServiceConnectionsc=
new
ServiceConnection(){
46
@Override
47
public
void
onServiceDisconnected(ComponentNamename){
48
musicService=
null
;
49
Log.d(TAG,
"inonServiceDisconnected"
);
50
}
51
52
@Override
53
public
void
onServiceConnected(ComponentNamename,IBinderservice){
54
musicService=((BindMusicService.MyBinder)(service)).getService();
55
if
(musicService!=
null
){
56
musicService.play();
57
}
58
59
Log.d(TAG,
"inonServiceConnected"
);
60
}
61
};
62
}
这里使用了bindService(intent,sc,Context.BIND_AUTO_CREATE);来启动服务的,
我们需要定义ServiceConnectionnn,并实现里面的方法,当服务绑定成功后会调用ServiceConnectionnn中的回调函数:
publicvoidonServiceConnected(ComponentNamename,IBinderservice),

调函数里面使用musicService=
((BindMusicService.MyBinder)(service)).getService();来获取BindMusicService服
务对象,有了BindMusicService实例对象,就可以调用服务提供的各种控制音乐播放的哦功能。
下面看看BindMusicService.java的实现:

01
/**
02
*@authorallin.dev
03
*http://allin.cnblogs.com/
04
*/
05
public
class
BindMusicService
extends
Service{
06
07
private
static
final
StringTAG=
"MyService"
;
08
private
MediaPlayermediaPlayer;
09
10
private
final
IBinderbinder=
new
MyBinder();
11
12
public
class
MyBinder
extends
Binder{
13
BindMusicServicegetService(){
14
return
BindMusicService.
this
;
15
}
16
}
17
18
/*
19
*(non-Javadoc)
20
*
21
*@seeandroid.app.Service#onBind(android.content.Intent)
22
*/
23
@Override
24
public
IBinderonBind(Intentintent){
25
Log.d(TAG,
"onBind"
);
26
play();
27
return
binder;
28
}
29
30
@Override
31
public
void
onCreate(){
32
super
.onCreate();
33
34
Log.d(TAG,
"onCreate"
);
35
Toast.makeText(
this
,
"showmediaplayer"
,Toast.LENGTH_SHORT).show();
36
37
38
}
39
40
@Override
41
public
void
onDestroy(){
42
super
.onDestroy();
43
44
Log.d(TAG,
"onDestroy"
);
45
Toast.makeText(
this
,
"stopmediaplayer"
,Toast.LENGTH_SHORT);
46
if
(mediaPlayer!=
null
){
47
mediaPlayer.stop();
48
mediaPlayer.release();
49
}
50
}
51
52
53
public
void
play(){
54
if
(mediaPlayer==
null
){
55
mediaPlayer=MediaPlayer.create(
this
,R.raw.tmp);
56
mediaPlayer.setLooping(
false
);
57
}
58
if
(!mediaPlayer.isPlaying()){
59
mediaPlayer.start();
60
}
61
}
62
63
public
void
pause(){
64
if
(mediaPlayer!=
null
&&mediaPlayer.isPlaying()){
65
mediaPlayer.pause();
66
}
67
}
68
69
public
void
stop(){
70
if
(mediaPlayer!=
null
){
71
mediaPlayer.stop();
72
try
{
73
//在调用stop后如果需要再次通过start进行播放,需要之前调用prepare函数
74
mediaPlayer.prepare();
75
}
catch
(IOExceptionex){
76
ex.printStackTrace();
77
}
78
}
79
}
80
81
}

们看到Service中有个返回IBinder对象的onBind方法,这个方法会在Service被绑定到其他程序上时被调用,而这个IBinder对
象和之前看到的onServiceConnected方法中传入的那个IBinder是同一个东西。应用和Service间就依靠这个IBinder对象
进行通信。
启动后的界面如下图:


[源码下载]

下一篇《androidservice学习(下)》会介绍通过AIDL对Service进行远程调用

转自:http://www.cnblogs.com/allin/archive/2010/05/15/1736458.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: