android service 学习
来源:互联网 发布:profili软件怎么用 编辑:程序博客网 时间:2024/04/30 09:39
Service是android 系统中的一种组件,它跟Activity的级别差不多,但是他不能自己运行,只能后台运行,并且可以和其他组件进行交互。Service的启动有两种方式:context.startService() 和 context.bindService()。
使用context.startService() 启动Service是会会经历:
context.startService() ->onCreate()- >onStart()->Service running
context.stopService() | ->onDestroy() ->Service stop
如果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()->Service running
onUnbind() -> onDestroy() ->Service stop
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来启动本地的服务。
而在下一篇《android service 学习(下) 》会介绍通过AIDL对Service进行远程调用。
下面是整个应用启动界面:
先从使用startService启动Service学起
首先编写一个Activity
01
public
class
PlayMusic
extends
Activity
implements
OnClickListener {
02
private
static
final
String TAG =
"PlayMusic"
;
03
private
Button playBtn;
04
private
Button stopBtn;
05
private
Button pauseBtn;
06
private
Button exitBtn;
07
private
Button closeBtn;
08
09
//....(详见源码)
10
11
@Override
12
public
void
onClick(View v) {
13
int
op = -
1
;
14
Intent intent =
new
Intent(
"org.allin.android.musicService"
);
15
16
//广播用
17
// Intent intent = new Intent("org.allin.android.musicReceiver");
18
19
switch
(v.getId()) {
20
case
R.id.play:
21
Log.d(TAG,
"onClick: playing muic"
);
22
op =
1
;
23
break
;
24
case
R.id.stop:
25
Log.d(TAG,
"onClick: stoping music"
);
26
op =
2
;
27
break
;
28
case
R.id.pause:
29
Log.d(TAG,
"onClick: pausing music"
);
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
Bundle bundle =
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 ,ntent intent = new Intent("org.allin.android.musicService");
"org.allin.android.musicService"是在AndroidManifest.xml文件中对service类的定义
1
<service android:enabled=
"true"
android:name=
".MusicService"
>
2
<intent-filter>
3
<action android:name=
"org.allin.android.musicService"
/>
4
</intent-filter>
5
</service>
把操作码放在Bundle中
Bundle bundle = new Bundle();
bundle.putInt("op", op);
intent.putExtras(bundle);
最后使用startService(intent);启动服务。
下面看看Service是怎么实现的。
MusicService.java
01
/**
02
* @author allin.dev
03
* http://allin.cnblogs.com/
04
*
05
*/
06
public
class
MusicService
extends
Service {
07
08
private
static
final
String TAG =
"MyService"
;
09
private
MediaPlayer mediaPlayer;
10
11
/*
12
* (non-Javadoc)
13
*
14
* @see android.app.Service#onBind(android.content.Intent)
15
*/
16
@Override
17
public
IBinder onBind(Intent arg0) {
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(Intent intent,
int
startId) {
41
Log.v(TAG,
"onStart"
);
42
if
(intent !=
null
) {
43
Bundle bundle = 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
(IOException ex) {
83
ex.printStackTrace();
84
}
85
}
86
}
87
88
}
服务 使用了系统自带MediaPlayer进行音乐的播放控制。 当调用了startService后服务会先调用onCreate,我们在里面对MediaPlayer进行初始化。接着会调用onStart,可以看到传递给startService()的Intent对象会传递给onStart()方法,这样我们就可以得到intent里面的操作码:
Iundle bundle = intent.getExtras();
int op = bundle.getInt("op");
然后更具定义好的操作码进行相应的f播放操作。启动后界面如下图:
图中的”close”和“exit”是不同的,close只是调用finish()退出当前的Activity,但是Service并没有关掉,音乐会继续播放。而exit就是调用了stopService(intent);来停止服务,Service会调用onDestroy()方法来对mediaPlayer进行停止和释放资源。
有时候如果服务只提供一些操作接口,我们也可以通过广播的g方式来启动服务。
首先要定义一个Receiver,并继承BroadcastReceiver,然后在AndroidManifest.xml中进行注册:
1
<receiver android:name=
".MusicReceiver"
>
2
<intent-filter>
3
<action android:name=
"org.allin.android.musicReceiver"
/>
4
</intent-filter>
5
</receiver>
Receiver的实现:
MusicReceiver.java
01
/**
02
* @author allin.dev
03
* http://allin.cnblogs.com/
04
*
05
*/
06
public
class
MusicReceiver
extends
BroadcastReceiver {
07
08
private
static
final
String TAG =
"MusicReceiver"
;
09
@Override
10
public
void
onReceive(Context context, Intent intent) {
11
Log.d(TAG,
"onReceive"
);
12
Intent it =
new
Intent(
"org.allin.android.musicService"
);
13
Bundle bundle = 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
Intent intent = new Intent("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
String TAG =
"PlayBindMusic"
;
04
private
Button playBtn;
05
private
Button stopBtn;
06
private
Button pauseBtn;
07
private
Button exitBtn;
08
09
private
BindMusicService musicService;
10
11
@Override
12
public
void
onClick(View v) {
13
14
switch
(v.getId()) {
15
case
R.id.play:
16
Log.d(TAG,
"onClick: binding srvice"
);
17
musicService.play();
18
break
;
19
case
R.id.stop:
20
Log.d(TAG,
"onClick: stoping srvice"
);
21
if
(musicService !=
null
){
22
musicService.stop();
23
}
24
break
;
25
case
R.id.pause:
26
Log.d(TAG,
"onClick: pausing srvice"
);
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
Intent intent =
new
Intent(
"org.allin.android.bindService"
);
42
bindService(intent, sc, Context.BIND_AUTO_CREATE);
43
44
}
45
private
ServiceConnection sc =
new
ServiceConnection() {
46
@Override
47
public
void
onServiceDisconnected(ComponentName name) {
48
musicService =
null
;
49
Log.d(TAG,
"in onServiceDisconnected"
);
50
}
51
52
@Override
53
public
void
onServiceConnected(ComponentName name, IBinder service) {
54
musicService = ((BindMusicService.MyBinder)(service)).getService();
55
if
(musicService !=
null
){
56
musicService.play();
57
}
58
59
Log.d(TAG,
"in onServiceConnected"
);
60
}
61
};
62
}
这里使用了bindService(intent, sc, Context.BIND_AUTO_CREATE);来启动服务的,
我们需要定义ServiceConnectionnn,并实现里面的方法,当服务绑定成功后会调用ServiceConnectionnn中的回调函数:
public void onServiceConnected(ComponentName name, IBinder service),
回调函数里面使用musicService = ((BindMusicService.MyBinder)(service)).getService();来获取BindMusicService服务对象,有了BindMusicService实例对象,就可以调用服务提供的各种控制音乐播放的哦功能。
注意要在Activity的onCrate方法中调用connect(),这里顺便说下顺序:
调用connect()函数后就绑定服务,触发Service的onCreate方法,然后调用Service的onBind()方法,绑定完成后又回到Activity的onServiceConnected()方法,在这个方法中的参数IBinder server就是onBind()中返回的,此时我们就可以利用这个IBinder来操作service了。
下面看看BindMusicService.java的实现:
01
/**
02
* @author allin.dev
03
* http://allin.cnblogs.com/
04
*/
05
public
class
BindMusicService
extends
Service {
06
07
private
static
final
String TAG =
"MyService"
;
08
private
MediaPlayer mediaPlayer;
09
10
private
final
IBinder binder =
new
MyBinder();
11
12
public
class
MyBinder
extends
Binder {
13
BindMusicService getService() {
14
return
BindMusicService.
this
;
15
}
16
}
17
18
/*
19
* (non-Javadoc)
20
*
21
* @see android.app.Service#onBind(android.content.Intent)
22
*/
23
@Override
24
public
IBinder onBind(Intent intent) {
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
,
"show media player"
, 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
,
"stop media player"
, 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
(IOException ex) {
76
ex.printStackTrace();
77
}
78
}
79
}
80
81
}
我们看到Service中有个返回IBinder对象的onBind方法,这个方法会在Service被绑定到其他程序上时被调用,而这个IBinder对象和之前看到的onServiceConnected方法中传入的那个IBinder是同一个东西。应用和Service间就依靠这个IBinder对象进行通信。
启动后的界面如下图:
[源码下载]
- android service 学习(上)
- android service 学习(下)
- Android Service学习
- Android Service学习笔记
- android service 学习
- android service 学习(下)
- android service 学习(上)
- android service 学习(下)
- Android学习之Service
- android service学习列表
- Android学习之Service
- android service 学习(上)
- android service 学习(下)
- Android中的Service学习
- Android Service学习笔记
- Android学习--Service初步
- android service 学习(上)
- android service 学习(下)
- 1
- android 卡片式浏览
- Linux数据恢复专题——恢复丢失的分区(转载)
- Spring中XML配置文件的十二个最佳方法(上)
- 用JAVA实现的类FileOperate,包括文件建立,查询,删除等。。。
- android service 学习
- 卷积的意义
- Spring中XML配置文件的十二个最佳方法(下)
- android service 学习(下)
- Linux下tar.xz结尾的文件的解压方法
- 汉字转换拼音或拼音首字母(两个函数)--记录一下
- Linux libcurl使用 (收藏)
- 隐式声明与内建函数XXX不兼容
- myeclipse中java注释乱码的解决