在Android中Activity是前台进程,而Service则是后台进程。Activity是有界面的,Service是没有界面。那何时使用Service?最经典的例子是播放音乐时,你想退出音乐播放,而不想音乐因为界面的退出而停止播放。那么使用Service就很好的解决了这个问题。
Service的生命周期比较简单,具体状态如下:
状态 | 说明 |
onCreate | 创建 |
onStart | 启动 |
onBind | 与调用程序绑定启动 |
onUnbind | 松绑 |
onDestroy | 销毁 |
主要有两种形式,根据驱动方式的不同而划分:
1、不绑定启动:
onCreate() --> onStart --> onDestroy();
2、绑定启动:
onCreate() --> onBind --> onUnbind --> onDestroy();
当然,上面两种方式可以混合着用,例如: onCreate() --> onStart --> sonBind --> onUnbind --> sonDestroy()。有几点要注意的是:
1、一个Service可以启动多次,但绑定时,仅能绑定一次。
2、调用OnBind绑定程序时,只有两种情况Service才会销毁:第一种是绑定它的Activity对象结束;第二种是调用OnUnbind方法松绑。
3、对于调用OnStart启动的Service,它不会随着调用它的Activity结束而结束,只有等它自动结束或调用Kiill方法才行。这也是实现即使界面退出,音乐仍然继续播放的关键。虽然Service是在Activity中调用,但Activity只起到启动它的作用,而Service后续的操作,不会受到Activity关闭的影响。
4、只有OnBind绑定程序后,才能调用OnUnbind方法,否则会报错。
下面,列举个例子看看:
1、启动Service--->关闭Service:
2、绑定Service---->松绑Service:
这里顺便说说绑定Service的操作:
(1)定义一个继承Service的类:
public class MyServiece extends Service { .......... }
(2)在该Service类里定义一个实现Binder的类,用于程序绑定Service是回调,使得触发onServiceConnected事件:
/** * 用于Activity绑定时回调,调用ServiceConnection.onServiceConnected方法 * @author Kobi * */ public class MyBinder extends Binder{ MyServiece getService() { return MyServiece.this; } }
(3)在Activity声明一个实现ServiceConnection接口的匿名类,如下:
//绑定Service需要用到的对象,是Activity与Service间连接的中介 private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub Toast.makeText(ServiceTest.this, "The Program is Binding!", Toast.LENGTH_SHORT).show(); Log.e(activity, "onServiceConnected"); } @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub Log.e(activity, "onServiceDisconnected"); } };
(4)最后,采用绑定语句,启动Service:
Intent intent = new Intent(ServiceTest.this, MyServiece.class); ServiceTest.this.bindService(intent, serviceConnection, BIND_AUTO_CREATE);
程序代码如下:
1、布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:id="@+id/bt_startService" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="启动Service" /> <Button android:id="@+id/bt_stopService" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="关闭Service" /> <Button android:id="@+id/bt_bindService" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="绑定Service" /> <Button android:id="@+id/bt_unbindService" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="松绑Service" /> <Button android:id="@+id/bt_closeApplication" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="退出程序" /> </LinearLayout>
2、程序代码
Activity代码:
package com.myandroid.test; import android.app.Activity; import android.content.ComponentName; 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.Toast; public class ServiceTest extends Activity{ private Button bt_startServiect; private Button bt_stopServiect; private Button bt_bindServiect; private Button bt_unbindServiect; private Button bt_closeApp; private MyServiece myService; private final String activity = "Activity"; //绑定Service需要用到的对象,是Activity与Service间连接的中介 private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub Toast.makeText(ServiceTest.this, "The Program is Binding!", Toast.LENGTH_SHORT).show(); Log.e(activity, "onServiceConnected"); } @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub Log.e(activity, "onServiceDisconnected"); } }; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); InitView(); } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); Log.e("Activity", "onDestroy"); } /** * 初始化控件对象 */ private void InitView() { bt_startServiect = (Button) findViewById(R.id.bt_startService); bt_stopServiect = (Button) findViewById(R.id.bt_stopService); bt_bindServiect = (Button) findViewById(R.id.bt_bindService); bt_unbindServiect = (Button) findViewById(R.id.bt_unbindService); bt_closeApp = (Button) findViewById(R.id.bt_closeApplication); bt_startServiect.setOnClickListener(new ClickEvent()); bt_stopServiect.setOnClickListener(new ClickEvent()); bt_bindServiect.setOnClickListener(new ClickEvent()); bt_unbindServiect.setOnClickListener(new ClickEvent()); bt_closeApp.setOnClickListener(new ClickEvent()); } /** * 鼠标点击触发事件类 * @author Kobi * */ private class ClickEvent implements OnClickListener { @Override public void onClick(View v) { Intent intent = new Intent(ServiceTest.this, MyServiece.class); switch(v.getId()) { case R.id.bt_startService: //启动Service:OnCreate()->onStart() ServiceTest.this.startService(intent); break; case R.id.bt_stopService: //关闭Service:onDestroy() ServiceTest.this.stopService(intent); break; case R.id.bt_bindService: //绑定Service:OnCreate()->onBind() ServiceTest.this.bindService(intent, serviceConnection, BIND_AUTO_CREATE); break; case R.id.bt_unbindService: //松绑Service:onUnbind()->onDestroy() if("onBind".equals(myService.serviceState)) { //只有绑定了,才能松绑,否则报错 ServiceTest.this.unbindService(serviceConnection); } break; case R.id.bt_closeApplication://关闭程序 ServiceTest.this.finish(); break; default: break; } } } }
Service代码:
package com.myandroid.test; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log; public class MyServiece extends Service { private final String service = "Service"; public static String serviceState = ""; //这里要用static修饰,因为service绑定时,是整个Service类,而不是他的某个实例对象 private MyBinder mBinder = new MyBinder(); //用于Activity绑定时回调 @Override public IBinder onBind(Intent arg0) { //绑定Service,绑定后不能再绑定;只有松绑后,才可以再绑定。 // TODO Auto-generated method stub //被绑定的Service只有onUnbind(), Log.e(service, "onBind()"); serviceState = "onBind"; return mBinder; } @Override public void onCreate() { //创建Service // TODO Auto-generated method stub super.onCreate(); Log.e(service, "onCreate()"); serviceState = "onCreate"; } @Override public void onDestroy() { //销毁Service // TODO Auto-generated method stub super.onDestroy(); Log.e(service, "onDestroy()"); serviceState = "onDestroy"; } @Override public void onStart(Intent intent, int startId) {//启动Service,可以启动多次 // TODO Auto-generated method stub super.onStart(intent, startId); Log.e(service, "onStart()"); serviceState = "onStart"; } @Override public boolean onUnbind(Intent intent) { //松绑Service,会触发onDestroy() // TODO Auto-generated method stub //还有点要注意,只有绑定了Service,才能松绑, Log.e(service, "onUnbind()"); //否则会报错。 serviceState = "onUnbind"; return super.onUnbind(intent); } /** * 用于Activity绑定时回调,调用ServiceConnection.onServiceConnected方法 * @author Kobi * */ public class MyBinder extends Binder{ MyServiece getService() { return MyServiece.this; } } }
最后,要在AndroidManifest.xml添加Service的声明:
<application android:icon="@drawable/icon" android:label="@string/app_name"> 。。。。。。。。。 <service android:name=".MyService" android:exported="true"></service> </application>