Service是一个长期运行在后台,并不提供界面的应用组件。其余组件能够启动一个服务,而且即便用户切换到其余的应用,该服务仍可在后台继续运行。另外,组件能够把某个服务邦定到本身,来与其交互通讯,甚至包括执行进程间通讯(IPC)。所以在播放器的开发中,为了让播放音乐不依赖于具体的Activity,将播放音乐的控制放于Service中。html
Service和Activity同样,须要在AndroidMainfest.xml中进行配置,配置以下:android
1 <service 2 android:name="com.porco.service.PlayService" android:exported="false"> 3 <intent-filter> 4 <action android:name="PlayService" /> 5 </intent-filter> 6 </service>
在此处设置了android:exported这个属性。这是用于指示该服务是否可以被其余应用程序组件调用或跟它交互:若是设置为true,则可以被调用或交互,不然不能。设置为false时,只有同一个应用程序的组件或带有相同用户ID的应用程序才能启动或绑定该服务。
它的默认值依赖与该服务所包含的过滤器。没有过滤器则意味着该服务只能经过指定明确的类名来调用,这样就是说该服务只能在应用程序的内部使用(由于其余外部使用者不会知道该服务的类名),所以这种状况下,这个属性的默认值是false。另外一方面,若是至少包含了一个过滤器,则意味着该服务能够给外部的其余应用提供服务,所以默认值是true,此种状况下在Eclipse中会有警告信息:Exported service does not require permission。ide
Service的使用方式有两种:context.s在tartService() 和 context.bindService()。其生命周期分别是:post
context.startService() 启动流程:学习
context.startService() -> onCreate() -> onStartCommand() -> Service running -> context.stopService() -> onDestroy() -> Service stop 测试
若是Service尚未运行,则android先调用onCreate(),而后调用onStartCommand();ui
若是Service已经运行,则只调用onStartCommand(),因此一个Service的onStartCommand方法可能会重复调用屡次。 this
若是stopService的时候会直接onDestroy,若是是调用者本身直接退出而没有调用stopService的话,Service会一直在后台运行,该Service的调用者再启动起来后能够经过stopService关闭Service。url
因此调用startService的生命周期为:onCreate --> onStart (可屡次调用) --> onDestroyspa
context.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在一个生命周期中只能被调用一次。
在具体使用时,可分为如下三种状况:
1.startService启动服务。
2.bindService启动服务。
3.startService & bindService 启动服务。
为了测试不一样状况下的service的调用及生命周期,编写测试demo代码以下:
Activity部分·:
public class PlayActivity extends Activity { private Intent intent=new Intent("tService"); private Button mButtonBind; private Button mButtonUnbind; private Button mButtonplay; private Button mButtonStart; private Button mButtonStop; TestService tService; ServiceConnection conn=new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub Log.d("activity1","service service disconnected"); } @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub //System.out.println("bind ok"); Log.d("activity1","service connnected"); tService=((TestService.MBinder) service ).getService(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.player); //bindService(intent, conn, BIND_AUTO_CREATE); mButtonBind=(Button)findViewById(R.id.buttonbind); mButtonUnbind=(Button)findViewById(R.id.buttonunbind); mButtonplay=(Button)findViewById(R.id.buttonserviceplay); mButtonStart=(Button)findViewById(R.id.buttonstart); mButtonStop=(Button)findViewById(R.id.buttonstop); mButtonBind.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub bindService(intent, conn, BIND_AUTO_CREATE); Log.d("activity1","activity after bindservice"); } }); mButtonUnbind.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub unbindService(conn); Log.d("activity1","activity after unbindservice"); } }); mButtonplay.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub tService.play(); } }); mButtonStart.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub startService(intent); Log.d("activity1","start service"); } }); mButtonStop.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub stopService(intent); Log.d("activity1","stop service"); } }); } }
Service部分:
public class TestService extends Service { private Thread mThread; @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub Log.d("service","onbind"); return new MBinder(); } class MBinder extends Binder{ public TestService getService(){ return TestService.this; } } @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); Log.d("service","service create"); } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); Log.d("service","service destory"); } @Override public boolean onUnbind(Intent intent) { // TODO Auto-generated method stub Log.d("service","service unbind"); return super.onUnbind(intent); } @Override public void onRebind(Intent intent) { // TODO Auto-generated method stub super.onRebind(intent); Log.d("service","service rebind"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub Log.d("service","service start"); return super.onStartCommand(intent, flags, startId); } public void play(){ Log.d("service","service play"); } }
1.startService启动服务:用于启动一个服务执行后台任务,不进行通讯,中止服务使用stopService。点击按钮调用startService()方法,输出结果以下:
2.bindService启动服务:该方法启动的服务要进行通讯,中止服务使用unbindService。点击按钮调用bindService()方法,输出结果以下:
3.startService & bindService 启动服务:Service将会一直在后台运行,同时调用stopService和unbindService才能中止服务。输出结果(一种)以下:
综合以上,能够得出:
1.在Service未启动时,不管是调用startService 仍是 bindService 方法,都会先调用service的onCreate()方法建立一个service服务。
2.在Service建立后销毁前,若是调用startService方法,每调用一次都会触发一次service的onStartCommand()方法;若是调用bindService方法,若是已绑定,则不会再触发service的onBind方法。
3.若是要销毁service,则须要调用对应的方法:startService--stopService ,bindService--unbindService,startService & bindService--stopService &unbindService,才会触发service的onDestory方法。
此外,有一点须要注意的是,在执行bindService方法后,下一个语句的执行先于service的建立,所以,须要注意对于binder返回的对象的使用,防止出错。具体service和activity在同一进程中的运行关系及状况须要后续学习。
参考文档:
Android Service 服务(一)—— Service