Service是Android中四大组件之一
定义:
Service(服务)是一个没有用户界面在后台运行执行耗时操作的应用组件。其他应用组能够启动Service,并且当用户切换到另一外的应用场景,Service将持续在后台运行。另外,一个组件能够绑定到一个Service与之交互(IPC机制),如:一个Service可能会处理网络操作,播放音乐,操作文件I/O或者与内容提供者(content provide)交互,所有这些活动都是在后台进行。Service有两种状态:“启动”和“绑定”
启动状态:
通过StartService()启动的服务处于启动状态,一旦启动,Service就再后台运行,即使启动它的应用组件已经被销毁了。通常started的状态的Service执行单任务不会返回任何结果给启动者。比如当下载或者上传一个文件,这项操作完成时,Service应该停止它本身。
绑定状态:
另一种状态就是绑定状态,通过调用bindService()启动绑定,一个绑定的Service提供一个允许组件与Service交互的接口,可以发送请求、获取返回结果,还可以通过夸进程通信来交互(IPC)。绑定的Service只有当应用组件绑定后才能运行,多个组件可以绑定一个Service,当调用unBind()方法时,这个Service将会被销毁,
但是在使用Service的时候也需要注意:Service与activity一样都存在与当前进程的主线程中,所以一些阻塞UI的操作,比如耗时操作同样也不能放在Service中操作。如果需要处理这一类耗时操作则需要另外开启一个线程来处理诸如网络请求的耗时操作。如果在Service里进行一些耗时CPU和耗时操作,可能会引起ANR警告,这时应用会弹出是否强制关闭的提示。所以对Service的理解就是和activity评级的,只不过是看不见的,在后台运行的一个组件,这个也是为什么Service和activity同被说为Android的基本组件。
Service生命周期中的一些方法:
通过这个图可以看到,两种启动Service的方式以及他们的生命周期,bindservice的不同之处在于当绑定的组件销毁后,对应的Service也就被kill了。Service的声明周期相比与activity的简单了许多,只要好好理解两种启动Service方式的异同就行了
Service生命周期也涉及一些回调方法,这些方法都不用调用父类方法,具体如下:
public class ExampleService extends Service {
int mStartMode; // indicates how to behave if the service is killed
IBinder mBinder; // interface for clients that bind
boolean mAllowRebind; // indicates whether onRebind should be used
@Override
public void onCreate() {
// The service is being created
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// The service is starting, due to a call to startService()
return mStartMode;
}
@Override
public IBinder onBind(Intent intent) {
// A client is binding to the service with bindService()
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
// All clients have unbound with unbindService()
return mAllowRebind;
}
@Override
public void onRebind(Intent intent) {
// A client is binding to the service with bindService(),
// after onUnbind() has already been called
}
@Override
public void onDestroy() {
// The service is no longer used and is being destroyed
}
}
关于Service生命周期还有一张比较容易懂的图(来源于网络)
然后这里也稍微说下Service的一个子类IntentService:
IntentService使用队列的方式将请求Intent加入队列,然后开启一个worker thread(线程)来处理 队列中intent,对于异步的startService请求,IntentSetvice会处理完成一个之后再处理第二个。
看下面IntentService的具体实现方式
public class HelloIntentService extends IntentService {
/**
* A constructor is required, and must call the super IntentService(String)
* constructor with a name for the worker thread.
*/
public HelloIntentService() {
super("HelloIntentService");
}
/**
* The IntentService calls this method from the default worker thread with
* the intent that started the service. When this method returns, IntentService
* stops the service, as appropriate.
*/
@Override
protected void onHandleIntent(Intent intent) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
}
}
关于停止Service,如果service是非绑定的,最终当任务完成时,为了节省系统资源,一定要停止service,可以通过stopSelf()来停止,也可以在其他组件中通过stopService()来停止,绑定的service可以通过onUnBind()来停止service。
下面看一个实例:
xml布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="启动Service"
android:id="@+id/start" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="停止Service"
android:id="@+id/stop" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="绑定Service"
android:id="@+id/bind" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="解除Service"
android:id="@+id/unbind" />
</LinearLayout>
MainActivity.class
/**
* User: x.j
* Date: 2015-03-05
* Time: 10:40
* service测试
*/
public class ServiceActivity extends Activity implements View.OnClickListener {
private Button btnStart, btnStop, btnBind, btnUnbind;
private static final String TAG = "ServiceActivity";
private backgroundService myService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.uiservice);
btnStart = (Button) findViewById(R.id.start);
btnStop = (Button) findViewById(R.id.stop);
btnBind = (Button) findViewById(R.id.bind);
btnUnbind = (Button) findViewById(R.id.unbind);
btnStart.setOnClickListener(this);
btnStop.setOnClickListener(this);
btnBind.setOnClickListener(this);
btnUnbind.setOnClickListener(this);
}
/**
*
* 点击动作
* @param v
*/
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setClass(ServiceActivity.this, backgroundService.class);
switch (v.getId()) {
case R.id.start:
//启动Service
startService(intent);
break;
case R.id.stop:
//停止服务
stopService(intent);
break;
case R.id.bind:
//绑定服务
bindService(intent,conn, Service.BIND_AUTO_CREATE);
break;
case R.id.unbind:
//接触绑定
unbindService(conn);
break;
}
}
/**
* 1.Service中需要创建一个现实IBinder的内部类(也就是必须在继承Service后必须实现的)在OnBind()方法中需返回一个IBinder实力
* 不然onServiceConnected方法不会调用。
* 2.ServiceConnection的回调方法onServiceDisConnected()在连接正常关闭的情况下是不会被调用的,该方法只在Service被破坏了
* 或者被杀死的时候调用.例如,系统资源不足,要关闭一些Service,刚好连接绑定的Service是被关闭之一,
* 这个时候onServiceDisconnected()就会被调用。
*/
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Utility.e(TAG,"连接成功");
//当Service连接建立成功后,提供给客户端与Service交互的对象(根据Android Doc翻译)
myService = ((backgroundService.MyBinder)service).getBackgroundService();
//
}
@Override
public void onServiceDisconnected(ComponentName name) {
Utility.e(TAG ,"断开连接");
myService = null;
}
};
}
Service.class
public class backgroundService extends Service{
private static final String TAG = "MyService";
private final IBinder myBinder = new MyBinder();
/**
* 吊用startService 方法或者bindService方法时 创建Service时(当前Service为创建)调用该方法
*/
@Override
public void onCreate() {
super.onCreate();
Utility.e(TAG, "onCreate()");
Utility.ToastInfo(this,"onCreate()");
}
/**
* 吊用startService方法启动Service时调用该方法
* @param intent
* @param startId
*/
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Utility.e(TAG, "onStart()");
Utility.ToastInfo(this,"onStart()");
}
/**
* 必须要实现的方法
* @param intent
* @return
*/
@Override
public IBinder onBind(Intent intent) {
Utility.e(TAG,"onBind()");
Utility.ToastInfo(this,"onBind()");
return myBinder;
}
/**
* 提供给客户端访问
*/
public class MyBinder extends Binder{
public backgroundService getBackgroundService(){
return backgroundService.this;
}
}
/**
* Service创建并启动后在调用stopService方法或者unbindService方法时调用该方法
*/
@Override
public void onDestroy() {
super.onDestroy();
Utility.e(TAG, "onDestroy()");
Utility.ToastInfo(this,"onCreate()");
}
@Override
public boolean onUnbind(Intent intent) {
Utility.e(TAG, "onUnbind()");
return super.onUnbind(intent);
}
@Override
public void onRebind(Intent intent) {
Utility.e(TAG, "onRebind()");
super.onRebind(intent);
}
}
AndroidManifest.xml注册Service
<!--注册Service-->
<service android:name="com.xj.server.backgroundService">
<intent-filter>
<action android:name=".backgroundService"/>
</intent-filter>
</service>