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

android service 学习(上)

2011-05-26 11:35 549 查看
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

view source
print
?

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类的定义

view source
print
?

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

 

view source
print
?

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中进行注册:

view source
print
?

1

<receiver android:name=

".MusicReceiver"

>

2

<intent-filter>

3

<action android:name=

"org.allin.android.musicReceiver"

/>

4

</intent-filter>

5

</receiver>

 

Receiver的实现:

 

MusicReceiver.java

view source
print
?

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

view source
print
?

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

BindMusicServicemusicService;

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实例对象,就可以调用服务提供的各种控制音乐播放的哦功能。

下面看看BindMusicService.java的实现:

 

 

view source
print
?

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

        

BindMusicServicegetService() {

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对象

进行通信。

启动后的界面如下图:



[源码下载
]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息