Service是android 系统中的四大组件之一(Activity、Service、BroadcastReceiver、ContentProvider)
它跟Activity的级别差不多,但不能自己运行只能后台运行,并且可以和其他组件进行交互。service可以在很多场合的应用中使用,
比如播放多媒体的时候用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD卡上文件的变化,
再或者在后台记录你地理信息位置的改变等等,总之服务总是藏在后台的。
Service的启动有两种方式:context.startService() 和 context.bindService()
二、 Service启动流程
context.startService() 启动流程:
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()启动流程:
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生命周期
Service的生命周期并不像Activity那么复杂,它只继承了onCreate()、onStart()、onDestroy()三个方法
当我们第一次启动Service时,先后调用了onCreate()、onStart()这两个方法;当停止Service时,则执行onDestroy()方法。
这里需要注意的是,如果Service已经启动了,当我们再次启动Service时,不会在执行onCreate()方法,而是直接执行onStart()方法。
它可以通过Service.stopSelf()方法或者Service.stopSelfResult()方法来停止自己,只要调用一次stopService()方法便可以停止服务,无论调用了多少次的启动服务方法。
四例子。创建一个MyService 的Service
package com.wyd.study.service;
import com.wyd.study.DBG;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
public class MyService extends Service {
private static final String TAG = "MyService";
/** onBind里面会返回一个Binder,所以新建个实例给返回。在这个实例里面有能够
* 返回这个服务的实例。从而在ServiceConnection里面能够获取到这个Service
* 能够调用这个Service相应的东西
* */
private MyBinder mBinder = new MyBinder();
private boolean mQuit;
@Override
public IBinder onBind(Intent intent) {
DBG.log(TAG, DBG._FUNC_());
return mBinder;
}
@Override
public void onCreate() {
DBG.log(TAG, DBG._FUNC_());
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
DBG.log(TAG, DBG._FUNC_());
/** 这个是新的的测试线程。*/
new Thread() {
public void run() {
mQuit = false;
while (!mQuit) {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
DBG.log(TAG, DBG._FUNC_());
}
};
}.start();
// return START_NOT_STICKY;
return START_STICKY;
}
@Override
public void onDestroy() {
DBG.log(TAG, DBG._FUNC_());
mQuit = true;
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
DBG.log(TAG, DBG._FUNC_());
return super.onUnbind(intent);
}
public class MyBinder extends Binder {
MyService getService() {
return MyService.this;
}
}
}
操作的activity类。里面定义了四个按钮,分别是启动服务,停止服务。绑定服务,解绑服务等功能。
/**
* 实验结果是
* 1、如果service没有启动过,调用bind后退出Acitivity或者调用unbind都会Destory
* 2、如果service同个start启动过,只能调用stop,不然不会Destory
* 3、调用bind后才能调用unbind,不然会出错.
* @author WangYD
* @time 2015年8月5日
*
*/
public class ServiceCtrlActivity extends Activity implements OnClickListener {
private static final String TAG = "ServiceCtrlActivity";
private TextView tv = null;
private MyService mMyService = null;
private static final int[] btns = new int[] { R.id.service_btn_start,
R.id.service_btn_stop, R.id.service_btn_bind,
R.id.service_btn_unbind, };
// 这里需要用到ServiceConnection在Context.bindService和context.unBindService()里用到
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 这里的IBinder service 是从 service.onBind 返回的,里面是通信信息的存放的地方
DBG.log(TAG, DBG._FUNC_());
mMyService = ((MyService.MyBinder) service).getService();
tv.setText("I am from Service" + mMyService.toString());
}
// 类ServiceConnection中的onServiceDisconnected()方法在正常情况下是不被调用的
// 它的调用时机是当Service服务被异外销毁时,例如内存的资源不足时这个方法才被自动调用。
@Override
public void onServiceDisconnected(ComponentName name) {
DBG.log(TAG, DBG._FUNC_());
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service);
tv = (TextView) findViewById(R.id.service_tv);
for (int btn : btns) {
findViewById(btn).setOnClickListener(this);
}
}
@Override
public void onClick(View v) {
Intent i = null;
i = new Intent(ServiceCtrlActivity.this, MyService.class);
switch (v.getId()) {
case R.id.service_btn_start:
startService(i);
break;
case R.id.service_btn_stop:
stopService(i);
break;
case R.id.service_btn_bind:
bindService(i, mServiceConnection, BIND_AUTO_CREATE);
break;
case R.id.service_btn_unbind:
unbindService(mServiceConnection);
break;
default:
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
DBG.log(TAG, DBG._FUNC_());
}
}
log分析1
//启动应用
08-06 09:43:33.513: I/DBG(353): MainActivity-> onCreate
//调用startService
08-06 09:43:56.262: I/DBG(353): MyService-> onCreate
08-06 09:43:56.264: I/DBG(353): MyService-> onStartCommand
//调用stopService
08-06 09:44:04.382: I/DBG(353): MyService-> onDestroy
//重新调用startService 启动service
08-06 09:44:19.658: I/DBG(353): MyService-> onCreate
08-06 09:44:19.659: I/DBG(353): MyService-> onStartCommand
//直接退出应用后再启动应用
08-06 09:44:39.105: I/DBG(353): MainActivity-> onCreate
//调用startService 启动service 并没有调用onCreate
08-06 09:44:44.187: I/DBG(353): MyService-> onStartCommand
//直接在任务管理器里面杀死应用。应用在onStartCommand 里面return START_STICKY
时,还会调用下面的两句话,说明服务还在。如果返回START_NOT_STICKY是时候。则什么也
看不到,连onDestroy都看不到。这个就很难说明服务还在不在
(实际上是不在的,可以在service增加个测试线程,不断的打印log)。区别就是START_STICKY
在被系统自己杀死进程的时候会重新启动。但是这个有个时间,所以Service会有点间隔
08-06 09:45:00.109: I/DBG(580): MyService-> onCreate
08-06 09:45:00.110: I/DBG(580): MyService-> onStartCommand
log分析2
//bindService
08-06 10:08:58.843: I/DBG(2937): MyService-> onCreate
08-06 10:08:58.851: I/DBG(2937): MyService-> onBind
08-06 10:08:58.854: I/DBG(2937): ServiceCtrlActivity-> onServiceConnected
//unbindService
08-06 10:09:07.297: I/DBG(2937): MyService-> onUnbind
08-06 10:09:07.298: I/DBG(2937): MyService-> onDestroy
//bindService
08-06 10:09:12.247: I/DBG(2937): MyService-> onCreate
08-06 10:09:12.248: I/DBG(2937): MyService-> onBind
08-06 10:09:12.259: I/DBG(2937): ServiceCtrlActivity-> onServiceConnected
//退出Activity的时候自动unbind
08-06 10:09:36.098: I/DBG(3059): MyService-> onUnbind
08-06 10:09:36.099: I/DBG(3059): MyService-> onDestroy