打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Android Service服务(三) bindService与remoteServic...

一、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

public class PlayBindMusic extends Activity implements OnClickListener {         private Button playBtn;         private Button stopBtn;         private Button pauseBtn;         private Button exitBtn;         private BindMusicService musicService;         @Override     public void onCreate(Bundle savedInstanceState) {             super.onCreate(savedInstanceState);                      setContentView(R.layout.bind_music_service);                      playBtn = (Button) findViewById(R.id.play);             stopBtn = (Button) findViewById(R.id.stop);             pauseBtn = (Button) findViewById(R.id.pause);             exitBtn = (Button) findViewById(R.id.exit);                      playBtn.setOnClickListener(this);             stopBtn.setOnClickListener(this);             pauseBtn.setOnClickListener(this);             exitBtn.setOnClickListener(this);                      connection();         }                  private void connection() {             Intent intent = new Intent("com.homer.bind.bindService");             bindService(intent, sc, Context.BIND_AUTO_CREATE);          // bindService         }                  @Override     public void onClick(View v) {             switch (v.getId()) {             case R.id.play:                 musicService.play();                 break;             case R.id.stop:                 if (musicService != null) {                     musicService.stop();                 }                 break;             case R.id.pause:                 if (musicService != null) {                     musicService.pause();                 }                 break;             case R.id.exit:                 this.finish();                 break;             }         }                  private ServiceConnection sc = new ServiceConnection() {                      @Override         public void onServiceConnected(ComponentName name, IBinder service) {       //connect Service                 musicService = ((BindMusicService.MyBinder) (service)).getService();                 if (musicService != null) {                     musicService.play();        // play music                 }             }                              @Override         public void onServiceDisconnected(ComponentName name) {                 //disconnect Service                 musicService = null;             }         };         @Override     public void onDestroy(){             super.onDestroy();                              if(sc != null){                 unbindService(sc);             }         }     }

public class BindMusicService extends Service { private MediaPlayer mediaPlayer; private final IBinder binder = new MyBinder(); public class MyBinder extends Binder { BindMusicService getService() { return BindMusicService.this; } } @Override public IBinder onBind(Intent intent) { return binder; } @Override public void onCreate() { super.onCreate(); Toast.makeText(this, "show media player", Toast.LENGTH_SHORT).show(); } @Override public void onDestroy() { super.onDestroy(); Toast.makeText(this, "stop media player", Toast.LENGTH_SHORT); if(mediaPlayer != null){ mediaPlayer.stop(); mediaPlayer.release(); } } public void play() { if (mediaPlayer == null) { mediaPlayer = MediaPlayer.create(this, R.raw.tmp); mediaPlayer.setLooping(false); } if (!mediaPlayer.isPlaying()) { mediaPlayer.start(); } } public void pause() { if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.pause(); } } public void stop() { if (mediaPlayer != null) { mediaPlayer.stop(); try { mediaPlayer.prepare(); // 在调用stop后如果需要再次通过start进行播放,需要之前调用prepare函数 } catch (IOException ex) { ex.printStackTrace(); } } } }

AndroidManifest.xml

<service android:name=".bind.BindMusicService" android:enabled="true" > <intent-filter> <action android:name="com.homer.bind.bindService" /> </intent-filter> </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

package com.homer.remote; interface IMusicControlService{ void play(); void stop(); void pause(); }

使用eclipse的Android插件,会根据这个aidl文件生成一个Java接口类,生成的接口类中会有一个内部类Stub类, Service来继承该Stub类:

Service

public class RemoteMusicService extends Service { private MediaPlayer mediaPlayer; @Override public IBinder onBind(Intent intent) { return binder; } private final IMusicControlService.Stub binder = new IMusicControlService.Stub() { @Override public void play() throws RemoteException { if (mediaPlayer == null) { mediaPlayer = MediaPlayer.create(RemoteMusicService.this, R.raw.tmp); mediaPlayer.setLooping(false); } if (!mediaPlayer.isPlaying()) { mediaPlayer.start(); } } @Override public void pause() throws RemoteException { if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.pause(); } } @Override public void stop() throws RemoteException { if (mediaPlayer != null) { mediaPlayer.stop(); try { mediaPlayer.prepare(); // 在调用stop后如果需要再次通过start进行播放,需要之前调用prepare函数 } catch (IOException ex) { ex.printStackTrace(); } } } }; @Override public void onDestroy() { super.onDestroy(); if(mediaPlayer != null){ mediaPlayer.stop(); mediaPlayer.release(); } } }


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

Activity

public class PlayRemoteMusic extends Activity implements OnClickListener {         private Button playBtn;         private Button stopBtn;         private Button pauseBtn;         private Button exitBtn;         private IMusicControlService musicService;         @Override     public void onCreate(Bundle savedInstanceState) {             super.onCreate(savedInstanceState);             setContentView(R.layout.remote_music_service);             playBtn = (Button) findViewById(R.id.play);             stopBtn = (Button) findViewById(R.id.stop);             pauseBtn = (Button) findViewById(R.id.pause);             exitBtn = (Button) findViewById(R.id.exit);             playBtn.setOnClickListener(this);             stopBtn.setOnClickListener(this);             pauseBtn.setOnClickListener(this);             exitBtn.setOnClickListener(this);             connection();         }         private void connection() {             Intent intent = new Intent("com.homer.remote.remoteMusicReceiver");             bindService(intent, sc, Context.BIND_AUTO_CREATE);              // bindService         }         @Override     public void onClick(View v) {             try {                 switch (v.getId()) {                 case R.id.play:                     musicService.play();                     break;                 case R.id.stop:                     if (musicService != null) {                         musicService.stop();                     }                     break;                 case R.id.pause:                     if (musicService != null) {                         musicService.pause();                     }                     break;                 case R.id.exit:                     this.finish();                     break;                 }             } catch (RemoteException e) {                 e.printStackTrace();             }         }         private ServiceConnection sc = new ServiceConnection() {             @Override         public void onServiceConnected(ComponentName name, IBinder service) {       //connect Service                 musicService = IMusicControlService.Stub.asInterface(service);             }             @Override         public void onServiceDisconnected(ComponentName name) {                 //disconnect Service                 musicService = null;             }                  };         @Override     public void onDestroy(){             super.onDestroy();             if(sc != null){                 unbindService(sc);              // unBindService             }         }     }

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等)

源码下载:http://download.csdn.net/detail/sunboy_2050/4149839



本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
android service 学习(上)
Android Service 服务(一)
Android Service生命周期及用法
Android中的Service,潜在的服务者。
深入理解Android的startservice和bindservice
Android 服务(Service) | 菜鸟教程
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服