Service 服务:
一个Service 是一段长生命周期的,没有用户界面的程序,可以用来开发如监控类程序。
比较好的一个例子就是一个正在从播放列表中播放歌曲的媒体播放器。在一个媒体播放器的应用中,应该会有多个activity,让使用者可以选择歌曲并播放歌曲。然而,音乐重放这个功能并没有对应的activity,因为使用者当然会认为在导航到其它屏幕时音乐应该还在播放的。
在这个例子中,媒体播放器这个activity 会使用Context.startService()来启动一个service,从而可以在后台保持音乐的播放。同时,系统也将保持这个service 一直执行,直到这个service 运行结束。另外,我们还可以通过使用Context.bindService()方法,连接到一个service 上(如果这个service 还没有运行将启动它)。当连接到一个service 之后,我们还可以使用service 提供的接口与它进行通讯。拿媒体播放器这个例子来说,我们还可以进行暂停、重播等操作。
Service使用步骤如下
1>继承service类
2>AndroidManifast.xml配置清单文件中<application>节点里对服务进行配置
<service name=".SMSService"/>
服务不能自己运行,需要通过Contex.startService()或Contex.bindService()启动服务
1.通过startService()方法启动的服务于调用者没有关系,即使调用者关闭了,服务仍然运行,想停止服务要调用Context.stopService(),此时系统会调用onDestory(),使用此方法启动时,服务首次启动系统先调用服务的onCreate()-->onStart(),如果服务已经启动再次调用只会触发onStart()方法
2.使用bindService()启动的服务与调用者绑定,只要调用者关闭服务就终止,使用此方法启动时,服务首次启动系统先调用服务的onCreate()-->onBind(),如果服务已经启动再次调用不会再触发这2个方法,调用者退出时系统会调用服务的onUnbind()-->onDestory(),想主动解除绑定可使用Contex.unbindService(),系统依次调用onUnbind()-->onDestory();
Service服务生命周期:
Service完整的生命周期:从调用onCreate()开始直到调用onDestroy()结束
Service有两种使用方法:
1>以调用Context.startService()启动,而以调用Context.stopService()结束
2>以调用Context.bindService()方法建立,以调用Context.unbindService()关闭
service重要的生命周期方法
当用户调用startService ()或bindService()时,Service第一次被实例化的时候系统会调用,整个生命周期只调用1次这个方法,通常用于初始化设置。
注意:多次调用startService()或bindService()方法不会多次触发onCreate()方法
void onCreate()
当用户调用stopService()或unbindService()来停止服务时被系统调用,(整个生命周期只调用1次)用来释放onCreate()方法中创建的资源
void onDestroy()
通过startService()方法启动的服务
初始化结束后系统会调用该方法,用于处理传递给startService()的Intent对象。如音乐服务会打开Intent 来探明将要播放哪首音乐,并开始播放。注意:多次调用startService()方法会多次触发onStart()方法
void onStart(Intent intent)
通过bindService ()方法启动的服务
初始化结束后系统会调用该方法,用来绑定传递给bindService 的Intent 的对象。注意:多次调用bindService()时,如果该服务已启动则不会再触发此方法
IBinder onBind(Intent intent)
用户调用unbindService()时系统调用此方法,Intent 对象同样传递给该方法
boolean onUnbind(Intent intent)
如果有新的客户端连接至该服务,只有当旧的调用onUnbind()后,新的才会调用该方法
void onRebind(Intent intent)
补充:onCreate(Bundle savedInstanceState)与onSaveInstanceState(Bundle savedInstanceState)配合使用,见如下代码,达到显示activity被系统杀死前的状态
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (null != savedInstanceState) {
String _userid = savedInstanceState.getString("StrUserId");
String _uid = savedInstanceState.getString("StrUid");
String _serverid = savedInstanceState.getString("StrServerId");
String _servername = savedInstanceState.getString("StrServerName");
int _rate = savedInstanceState.getInt("StrRate");
//updateUserId(_userid);
//updateUId(_uid);
//updateServerId(_serverid);
//updateUserServer(_servername);
//updateRate(_rate);
}
}
@Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString("StrUserId", getUserId());
savedInstanceState.putString("StrUid", getUId());
savedInstanceState.putString("StrServerId", getServerId());
savedInstanceState.putString("StrServerName", getServerName());
savedInstanceState.putInt("StrRate", getRate());
}
下面通过一个简单demo看看分别通过两种方式启动service时,这些回调函数的执行过程。
(1)startService()
1.新建一个StartLocalServiceActivity.java文件,定义两个按钮用来启动和停止service
package com.alexzhou.servicedemo;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
//启动一个本地Service
public class StartLocalServiceActivity extends Activity implements
OnClickListener {
private Button startButton;
private Button stopButton;
private final String LOCAL_START_SERVICE_ACTION = "com.alexzhou.service.LOCAL_START_SERVICE";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.start_local_service);
findViews();
setListeners();
}
private void findViews() {
startButton = (Button) this.findViewById(R.id.start);
stopButton = (Button) this.findViewById(R.id.stop);
}
private void setListeners() {
startButton.setOnClickListener(this);
stopButton.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.start:
this.startService(new Intent(LOCAL_START_SERVICE_ACTION));
break;
case R.id.stop:
this.stopService(new Intent(LOCAL_START_SERVICE_ACTION));
break;
}
}
}
2.新建一个LocalService.java文件,这个就是本地service文件。
package com.alexzhou.servicedemo.service;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
//本地服务
public class LocalService extends Service {
private final String TAG = LocalService.class.getSimpleName();
private LocalBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
public LocalService getService() {
return LocalService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG, "onBind");
return mBinder;
}
@Override
public void onCreate() {
Log.e(TAG, "onCreate");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.e(TAG, "onDestroy");
super.onDestroy();
}
public String getContent() {
return "welcome access local service!";
}
}
点击停止服务按钮,此时会执行:onDestory()方法销毁service。
onCreate()方法在service第一次创建的时候会调用,如果该service已经运行了则不会执行该函数。
onStartCommand()方法是在其他组件通过调用startService()启动服务时才会执行。每次启动service时,onStartCommand()都会被执行。你多点几次启动服务按钮,会看到每次都会执行onStartCommand()。
(2) bindService()
创建一个BindLocalServiceActivity.java文件,也同样弄两个button来绑定和解绑服务。
package com.alexzhou.servicedemo;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.alexzhou.servicedemo.service.LocalService;
//绑定一个本地Service
public class BindLocalServiceActivity extends Activity implements
OnClickListener {
private TextView callbackView;
private Button bindButton;
private Button unbindButton;
private boolean isBind;
private final String LOCAL_BIIND_SERVICE_ACTION = "com.alexzhou.service.LOCAL_BIND_SERVICE";
private LocalService mLocalService = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.bind_local_service);
findViews();
setListeners();
callbackView.setText("Not attached.");
}
private void findViews() {
callbackView = (TextView) this.findViewById(R.id.callback);
bindButton = (Button) this.findViewById(R.id.bind);
unbindButton = (Button) this.findViewById(R.id.unbind);
}
private void setListeners() {
bindButton.setOnClickListener(this);
unbindButton.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.bind:
this.bindService(new Intent(LOCAL_BIIND_SERVICE_ACTION),
mConntectin, Context.BIND_AUTO_CREATE);
isBind = true;
callbackView.setText("binding...");
break;
case R.id.unbind: {
if (isBind) {
this.unbindService(mConntectin);
isBind = false;
callbackView.setText("unbind...");
}
}
break;
}
}
private ServiceConnection mConntectin = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName arg0) {
Log.i(BindLocalServiceActivity.class.getSimpleName(),
"onServiceDisConnected");
callbackView.setText("Disconnected!");
Toast.makeText(BindLocalServiceActivity.this,
R.string.remote_service_disconntected, Toast.LENGTH_SHORT)
.show();
}
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
Log.i(BindLocalServiceActivity.class.getSimpleName(),
"onServiceConnected");
mLocalService = ((LocalService.LocalBinder) binder).getService();
callbackView.setText("attached!" + mLocalService.getContent());
Toast.makeText(BindLocalServiceActivity.this,
R.string.remote_service_connected, Toast.LENGTH_SHORT)
.show();
}
};
@Override
protected void onDestroy() {
super.onDestroy();
if (isBind) {
this.unbindService(mConntectin);
isBind = false;
}
}
}
点击绑定服务按钮,从Logcat输出的信息中可以看出调用顺序:onCreate()->onBind() ->onServiceConnnected()
同理onCreate()只会在service第一次创建时执行。
点击解绑服务,会调用service的onDestory()方法。可以先调用startService(),然后再绑定该service,这样解除绑定的时候service就不会被销毁了,需要unbindService()和stopService()都调用,服务才会销毁。注意:连接正常关闭的情况下,上述代码中onServiceDisconnected是不会调用的,只有在异常关闭的时候调用,比如被kill了。