startService与bindService

分类:Android 7588人阅读 评论(4) 收藏 举报 service android application windows class

Service的生命周期Service的生命周期方法比Activity少一些,只有onCreate, onStart, onDestroy
我们有两种方式启动一个Service,他们对Service生命周期的影响是不一样的。

1 通过startService
Service会经历 onCreate -> onStart
stopService的时候直接onDestroy

如果是调用者(TestServiceHolder)自己直接退出而没有调用stopService的
话,Service会一直在后台运行。
下次TestServiceHolder再起来可以stopService。

2 通过bindService
Service只会运行onCreate, 这个时候 TestServiceHolder 和TestService绑定在一起

TestServiceHolder 退出了,Srevice就会调用onUnbind->onDestroyed
所谓绑定在一起就共存亡了。

那有同学问了,要是这几个方法交织在一起的话,会出现什么情况呢?
一个原则是Service的onCreate的方法只会被调用一次,就是你无论多少次的startService又 bindService,Service只被创建一次。如果先是bind了,那么start的时候就直接运行Service的onStart方法,如果先 是start,那么bind的时候就直接运行onBind方法。如果你先bind上了,就stop不掉了,对啊,就是stopService不好使了,只 能先UnbindService, 再StopService,所以是先start还是先bind行为是有区别的。

看起来情况很多,不过我会把这次的代码包括上回Activity生命周期的研究代码都贴上了,希望你喜欢!大家有兴趣可以回去点点按钮看看log,多看几遍就知道了。

Android中的服务和windows中的服务是类似的东西,服务一般没有用户操作界面,它运行于系统中不容易被用户发觉,可以使用它开发如监控之类的程序。服务的开发比较简单,如下:
第一步:继承Service类
public class SMSService extends Service { }

第二步:在AndroidManifest.xml文件中的<application>节点里对服务进行配置:
<service android:name=".SMSService" />

服务不能自己运行,需要通过调用Context.startService()或Context.bindService()方法启动服务。这两个方法都可以启动Service,但是它们的使用场合有所不同。使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。

如果打算采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。

如果打算采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()-->onDestroy()方法.

原文地址:http://www.80xin.com/viewthread.jsp?tid=121&extra=page%3D1%26amp%3Bfilter%3D2592000%26amp%3Borderby%3Dlastpost%26amp%3Bascdesc%3DDES


Android Service 服务(三)—— bindService与remoteService

分类:Android 6828人阅读 评论(0) 收藏 举报 service android button null 音乐 class

一、bindService简介

bindService是绑定Service服务,执行service服务中的逻辑流程。

service通过Context.startService()方法开始,通过Context.stopService()方法停止;也可以通过Service.stopSelf()方法或者Service.stopSelfResult()方法来停止自己。只要调用一次stopService()方法便可以停止服务,无论之前它被调用了多少次的启动服务方法。

客户端建立一个与Service的连接,并使用此连接与Service进行通话,通过Context.bindService()方法来绑定服务,Context.unbindService()方法来关闭服务。多个客户端可以绑定同一个服务,如果Service还未被启动,bindService()方法可以启动服务。

上面startService()和bindService()两种模式是完全独立的。你可以绑定一个已经通过startService()方法启动的服务。例如:一个后台播放音乐服务可以通过startService(intend)对象来播放音乐。可能用户在播放过程中要执行一些操作比如获取歌曲的一些信息,此时activity可以通过调用bindServices()方法与Service建立连接。这种情况下,stopServices()方法实际上不会停止服务,直到最后一次绑定关闭。


二、bindService启动流程

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在一个生命周期中只能被调用一次。详见:Android Service 服务(一)—— Service


三、bindService生命周期

像一个activity那样,一个service有些可以用来改变状态的生命周期方法,但是比activity的方法少,service生命周期方法只有三个public

void onCreate()

void onStart(Intent intent)

void onDestroy()

通过实现这三个生命周期方法,你可以监听service的两个嵌套循环的生命周期:

1、整个生命周期

service的整个生命周期是在onCreate()和onDestroy()方法之间。和activity一样,在onCreate()方法里初始化,在onDestroy()方法里释放资源。例如,一个背景音乐播放服务可以在onCreate()方法里播放,在onDestroy()方法里停止。

2、活动的生命周期

service的活动生命周期是在onStart()之后,这个方法会处理通过startServices()方法传递来的Intent对象。音乐service可以通过开打intent对象来找到要播放的音乐,然后开始后台播放。注: service停止时没有相应的回调方法,即没有onStop()方法,只有onDestroy()销毁方法。

onCreate()方法和onDestroy()方法是针对所有的services,无论它们是否启动,通过Context.startService()和Context.bindService()方法都可以访问执行。然而,只有通过startService()方法启动service服务时才会调用onStart()方法

如果一个service允许别人绑定,那么需要实现以下额外的方法:

IBinder onBind(Intent intent)

boolean onUnbind(Intent intent)

void onRebind(Intent intent)

onBind()回调方法会继续传递通过bindService()传递来的intent对象

onUnbind()会处理传递给unbindService()的intent对象。如果service允许绑定,onBind()会返回客户端与服务互相联系的通信句柄(实例)。

如果建立了一个新的客户端与服务的连接,onUnbind()方法可以请求调用onRebind()方法。


记住: 任何服务无论它怎样建立,默认客户端都可以连接,所以任何service都能够接收onBind()和onUnbind()方法



四、bindService示例

Activity

[java] view plain copy print ?
  1. publicclassPlayBindMusicextendsActivityimplementsOnClickListener{
  2. privateButtonplayBtn;
  3. privateButtonstopBtn;
  4. privateButtonpauseBtn;
  5. privateButtonexitBtn;
  6. privateBindMusicServicemusicService;
  7. @Override
  8. publicvoidonCreate(BundlesavedInstanceState){
  9. super.onCreate(savedInstanceState);
  10. setContentView(R.layout.bind_music_service);
  11. playBtn=(Button)findViewById(R.id.play);
  12. stopBtn=(Button)findViewById(R.id.stop);
  13. pauseBtn=(Button)findViewById(R.id.pause);
  14. exitBtn=(Button)findViewById(R.id.exit);
  15. playBtn.setOnClickListener(this);
  16. stopBtn.setOnClickListener(this);
  17. pauseBtn.setOnClickListener(this);
  18. exitBtn.setOnClickListener(this);
  19. connection();
  20. }
  21. privatevoidconnection(){
  22. Intentintent=newIntent("com.homer.bind.bindService");
  23. bindService(intent,sc,Context.BIND_AUTO_CREATE);//bindService
  24. }
  25. @Override
  26. publicvoidonClick(Viewv){
  27. switch(v.getId()){
  28. caseR.id.play:
  29. musicService.play();
  30. break;
  31. caseR.id.stop:
  32. if(musicService!=null){
  33. musicService.stop();
  34. }
  35. break;
  36. caseR.id.pause:
  37. if(musicService!=null){
  38. musicService.pause();
  39. }
  40. break;
  41. caseR.id.exit:
  42. this.finish();
  43. break;
  44. }
  45. }
  46. privateServiceConnectionsc=newServiceConnection(){
  47. @Override
  48. publicvoidonServiceConnected(ComponentNamename,IBinderservice){//connectService
  49. musicService=((BindMusicService.MyBinder)(service)).getService();
  50. if(musicService!=null){
  51. musicService.play();//playmusic
  52. }
  53. }
  54. @Override
  55. publicvoidonServiceDisconnected(ComponentNamename){//disconnectService
  56. musicService=null;
  57. }
  58. };
  59. @Override
  60. publicvoidonDestroy(){
  61. super.onDestroy();
  62. if(sc!=null){
  63. unbindService(sc);
  64. }
  65. }
  66. }

Service

[java] view plain copy print ?
  1. publicclassBindMusicServiceextendsService{
  2. privateMediaPlayermediaPlayer;
  3. privatefinalIBinderbinder=newMyBinder();
  4. publicclassMyBinderextendsBinder{
  5. BindMusicServicegetService(){
  6. returnBindMusicService.this;
  7. }
  8. }
  9. @Override
  10. publicIBinderonBind(Intentintent){
  11. returnbinder;
  12. }
  13. @Override
  14. publicvoidonCreate(){
  15. super.onCreate();
  16. Toast.makeText(this,"showmediaplayer",Toast.LENGTH_SHORT).show();
  17. }
  18. @Override
  19. publicvoidonDestroy(){
  20. super.onDestroy();
  21. Toast.makeText(this,"stopmediaplayer",Toast.LENGTH_SHORT);
  22. if(mediaPlayer!=null){
  23. mediaPlayer.stop();
  24. mediaPlayer.release();
  25. }
  26. }
  27. publicvoidplay(){
  28. if(mediaPlayer==null){
  29. mediaPlayer=MediaPlayer.create(this,R.raw.tmp);
  30. mediaPlayer.setLooping(false);
  31. }
  32. if(!mediaPlayer.isPlaying()){
  33. mediaPlayer.start();
  34. }
  35. }
  36. publicvoidpause(){
  37. if(mediaPlayer!=null&&mediaPlayer.isPlaying()){
  38. mediaPlayer.pause();
  39. }
  40. }
  41. publicvoidstop(){
  42. if(mediaPlayer!=null){
  43. mediaPlayer.stop();
  44. try{
  45. mediaPlayer.prepare();//在调用stop后如果需要再次通过start进行播放,需要之前调用prepare函数
  46. }catch(IOExceptionex){
  47. ex.printStackTrace();
  48. }
  49. }
  50. }
  51. }

AndroidManifest.xml

[css] view plain copy print ?
  1. <service
  2. android:name=".bind.BindMusicService"
  3. android:enabled="true">
  4. <intent-filter>
  5. <actionandroid:name="com.homer.bind.bindService"/>
  6. </intent-filter>
  7. </service>


五、代码解析

1、 Activity中,Intent intent = new Intent("com.homer.bind.bindService"); 构建一个service的action,然后bindService(intent, sc, Context.BIND_AUTO_CREATE); 绑定服务

2、 Activity中,通过private ServiceConnection sc = new ServiceConnection() 建立一个Service连接,onServiceConnected()获取Service实例,onServiceDisconnected()释放连接

3、 Service中,重载onBind(Intent intent)方法,返回Service实例(即BindMusicService)给Activity,然后执行onCreate()函数(注:bindService不执行onStart()函数)

4、 Activity中,通过返回的Service实例musicService,执行音乐播放的操作(play、pause、stop等)



六、Remote Service拓展

通常每个应用程序都在它自己的进程内运行,但有时需要在进程之间传递对象(IPC通信),你可以通过应用程序UI的方式写个运行在一个不同的进程中的service。在android平台中,一个进程通常不能访问其它进程中的内存区域。所以,他们需要把对象拆分成操作系统能理解的简单形式,以便伪装成对象跨越边界访问。编写这种伪装代码相当的枯燥乏味,好在android为我们提供了AIDL工具可以来做这件事。

AIDL(android接口描述语言)是一个IDL语言,它可以生成一段代码,可以使在一个android设备上运行的两个进程使用内部通信进程进行交互。如果你需要在一个进程中(例如在一个Activity中)访问另一个进程中(例如一个Service)某个对象的方法,你就可以使用AIDL来生成这样的代码来伪装传递各种参数。

要使用AIDL,Service需要以aidl文件的方式提供服务接口,AIDL工具将生成一个相应的java接口,并且在生成的服务接口中包含一个功能调用的stub服务桩类。Service的实现类需要去继承这个stub服务桩类。Service的onBind方法会返回实现类的对象,之后你就可以使用它了,参见下例:

IMusicControlService.aidl

[css] view plain copy print ?
  1. packagecom.homer.remote;
  2. interfaceIMusicControlService{
  3. voidplay();
  4. voidstop();
  5. voidpause();
  6. }

使用eclipse的Android插件,会根据这个aidl文件生成一个Java接口类,生成的接口类中会有一个内部类Stub类,Service来继承该Stub类: Service [java] view plain copy print ?
  1. publicclassRemoteMusicServiceextendsService{
  2. privateMediaPlayermediaPlayer;
  3. @Override
  4. publicIBinderonBind(Intentintent){
  5. returnbinder;
  6. }
  7. privatefinalIMusicControlService.Stubbinder=newIMusicControlService.Stub(){
  8. @Override
  9. publicvoidplay()throwsRemoteException{
  10. if(mediaPlayer==null){
  11. mediaPlayer=MediaPlayer.create(RemoteMusicService.this,R.raw.tmp);
  12. mediaPlayer.setLooping(false);
  13. }
  14. if(!mediaPlayer.isPlaying()){
  15. mediaPlayer.start();
  16. }
  17. }
  18. @Override
  19. publicvoidpause()throwsRemoteException{
  20. if(mediaPlayer!=null&&mediaPlayer.isPlaying()){
  21. mediaPlayer.pause();
  22. }
  23. }
  24. @Override
  25. publicvoidstop()throwsRemoteException{
  26. if(mediaPlayer!=null){
  27. mediaPlayer.stop();
  28. try{
  29. mediaPlayer.prepare();//在调用stop后如果需要再次通过start进行播放,需要之前调用prepare函数
  30. }catch(IOExceptionex){
  31. ex.printStackTrace();
  32. }
  33. }
  34. }
  35. };
  36. @Override
  37. publicvoidonDestroy(){
  38. super.onDestroy();
  39. if(mediaPlayer!=null){
  40. mediaPlayer.stop();
  41. mediaPlayer.release();
  42. }
  43. }
  44. }

客户端(Activity)应用连接到这个Service时,onServiceConnected方法将被调用,客户端就可以获得IBinder对象。参看下面的客户端onServiceConnected方法:

Activity

[java] view plain copy print ?
  1. publicclassPlayRemoteMusicextendsActivityimplementsOnClickListener{
  2. privateButtonplayBtn;
  3. privateButtonstopBtn;
  4. privateButtonpauseBtn;
  5. privateButtonexitBtn;
  6. privateIMusicControlServicemusicService;
  7. @Override
  8. publicvoidonCreate(BundlesavedInstanceState){
  9. super.onCreate(savedInstanceState);
  10. setContentView(R.layout.remote_music_service);
  11. playBtn=(Button)findViewById(R.id.play);
  12. stopBtn=(Button)findViewById(R.id.stop);
  13. pauseBtn=(Button)findViewById(R.id.pause);
  14. exitBtn=(Button)findViewById(R.id.exit);
  15. playBtn.setOnClickListener(this);
  16. stopBtn.setOnClickListener(this);
  17. pauseBtn.setOnClickListener(this);
  18. exitBtn.setOnClickListener(this);
  19. connection();
  20. }
  21. privatevoidconnection(){
  22. Intentintent=newIntent("com.homer.remote.remoteMusicReceiver");
  23. bindService(intent,sc,Context.BIND_AUTO_CREATE);//bindService
  24. }
  25. @Override
  26. publicvoidonClick(Viewv){
  27. try{
  28. switch(v.getId()){
  29. caseR.id.play:
  30. musicService.play();
  31. break;
  32. caseR.id.stop:
  33. if(musicService!=null){
  34. musicService.stop();
  35. }
  36. break;
  37. caseR.id.pause:
  38. if(musicService!=null){
  39. musicService.pause();
  40. }
  41. break;
  42. caseR.id.exit:
  43. this.finish();
  44. break;
  45. }
  46. }catch(RemoteExceptione){
  47. e.printStackTrace();
  48. }
  49. }
  50. privateServiceConnectionsc=newServiceConnection(){
  51. @Override
  52. publicvoidonServiceConnected(ComponentNamename,IBinderservice){//connectService
  53. musicService=IMusicControlService.Stub.asInterface(service);
  54. }
  55. @Override
  56. publicvoidonServiceDisconnected(ComponentNamename){//disconnectService
  57. musicService=null;
  58. }
  59. };
  60. @Override
  61. publicvoidonDestroy(){
  62. super.onDestroy();
  63. if(sc!=null){
  64. unbindService(sc);//unBindService
  65. }
  66. }
  67. }

Remote Service流程总结:

1、 Activity(客户端)中,Intent intent = new Intent("com.homer.remote.remoteMusicReceiver");构建intent,然后bindService(intent, sc, Context.BIND_AUTO_CREATE);绑定服务

2、 Activity(客户端)中,通过ServiceConnection()重载onServiceConnected()建立连接,获取Service.Stub实例;onServiceDisconnected()释放连接(与bindService类似)

3、 Service中,通过重载onBind(Intent intent) 返回Service.Stub实例,但Service.Stub类是由aidl文件生成的接口类中的一个内部类Stub类,Service来继承该Stub类

4、 Activity中,通过操作Service实例(musicService),执行音乐播放操作(play、pause、stop等)


源码下载



参考推荐:

Service(android developer)

Android Service 服务(一)—— Service

Android Service 服务(二)—— BroadcastReceiver

android中service和aidl详细整理

Android Service AIDL

android笔记--Service与AIDL


更多相关文章

  1. UIView的drawRect: 和 - (void)setNeedsDisplay 的一些理解
  2. 安装Android的Eclipse插件ADT遇到“requires 'org.eclipse.wst.s
  3. Android打包jar的两种方法
  4. 【安卓笔记】touch事件的分发和消费机制
  5. Android(安卓)Fragment的生命周期详解
  6. Android(安卓)TextView中显示图片
  7. Android(安卓)完全隐藏状态栏方法
  8. Android开发Android(安卓)studio之gradle打包apk重命名的方法
  9. Android(安卓)多媒体框架(2)—— android_media_MediaCodec.cpp源

随机推荐

  1. android 通过 button 弹出menu
  2. android-passwordsafe - Android(安卓)Pa
  3. Android(安卓)结束进程的方法
  4. Android的Bluetooth Profile与UUID
  5. Android(安卓)Unable to find instrument
  6. android webview ERR_UNKNOWN_URL_SCHEME
  7. Android(安卓)Studio v1.0 项目无法运行
  8. android中的两端对齐
  9. Android(安卓)AIDL 理解及开发要点
  10. android 静默安装 卸载 资料汇总