Android之四大元件(Service的開啟與關閉)
個人開發的微信小程式,目前功能是書籍推薦,後續會完善一些新功能,希望大家多多支援!
前言
服務(Service)是Android系統中的四大元件之一。服務主要用於兩個目的:後臺執行和跨程序訪問。通過啟動
一個服務,可以在不顯示介面的前提下在後臺執行指定的任務,這樣可以不影響使用者做其他事情。通過AIDL服務可以
實現不同程序之間的通訊,這也是服務的重要用途之一。
Service基礎
Service並沒有實際介面,而是一直在Android系統的後臺執行。一般使用Service為應用程式提供一些服務,或不
需要介面的功能,例如下載檔案、播放音訊等。
如何建立與配置Service
在日常開發中Service的建立與配置可以按照以下兩個步驟進行:
(1)定義一個繼承Service的子類。
(2)在AndroidManifest.xml檔案中配置該Service。
Service與Activity一樣,也有一個啟動到銷燬的過程,不過這個過程Service要比Activity簡單多了。一個服務實際
上是一個繼承自android.app.Service的類。檢視Service原始碼,可以看出Service實際上是一個抽象類,在這個抽象類
中有一個抽象方法onBind,因此我們在繼承一個Service類時,必須要實現這個方法。
public abstract class Service extends ContextWrapper implements ComponentCallbacks2 { ....... public abstract IBinder onBind(Intent intent); ....... }
下面類定義了一個Service元件。
public class MyFirstService extends Service{ public static final String TAG="MyFirstService"; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); Log.e(TAG, "--------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() { super.onDestroy(); Log.e(TAG, "--------onDestroy--------"); } }
以上程式碼完成了建立Service,接下來需要在AndroidMainfest.xml檔案中進行配置該Service,以下配置程式碼展示了
如何配置Service:
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.example.servicetest.startservice.MyFirstService" >
</service>
</application>
到了這一步我們的Service元件已經建立完畢。接著我們可以啟動Service了,在Android系統中啟動Service有兩種
方式,分別是startService和bindService。
startService使用
下面程式通過兩個按鈕進行啟動與停止Service,演示Service通過startService從建立到銷燬整個過程。
public class MyFirstService extends Service{
public static final String TAG="MyFirstService";
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.e(TAG, "--------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() {
super.onDestroy();
Log.e(TAG, "--------onDestroy--------");
}
}
兩個按鈕的點選事件:
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_startService:// startService
startService(serviceIntent);
break;
case R.id.btn_stoptService:// stopService
stopService(serviceIntent);
break;
default:
break;
}
}
以上是我們建立的Service元件,接下來對Service進行操作。
(1)當單擊一次啟動(startService)按鈕時:
(2)當服務被啟動後單擊一次停止(stopService)按鈕時:
從上面可以看出Service從建立到銷燬分別經歷了 onCreate---->onStartCommand---->onDestroy
(3)當我們重複開啟Service時:
從上圖可以看出,每當Service被建立時回撥onCreate方法,每次Service被啟動時都會回撥onStartCommand方
法,多次啟動一個已有的Service元件將不會再回調onCreate方法,但每次啟動時都會回撥onStartCommand方法。
其中,當我按下home鍵時,並沒有回撥onDestroy方法,也就是說此Service並沒有隨著Android系統的關閉而關
閉。
bindService的使用
使用startService方法啟動服務,當程式被強制退出時,並且沒有呼叫stopService來停止服務,Service會保持在
後臺一直執行,直到Android系統關閉或呼叫stopService方法後才會停止。如果我們希望在啟動服務的Activity關閉後
服務自動關閉,這就需要將Activity和Service進行繫結。
通過bindService方法可以將Activity和Service繫結。bindService方法的定義如下:
public boolean bindService(Intent service, ServiceConnection conn,int flags)
該方法的三個引數含義如下:
(1)service:該引數通過Intent指定要啟動的Service。
(2)conn:該引數的型別是ServiceConnection,負責連線Intent物件指定的服務。當訪問者與Service之間連線
成功時將回調ServiceConnecttion物件的onServiceConnected(ComponentName name,IBinder service)方法;當
Service所在的宿主程序由於異常終止或由於其他原因終止,導致該Service與訪問者之間斷開連線時回撥
ServiceConnection物件的onServiceDisconnected(ComponentName name)方法。
(3)flags:該引數是一個標誌位,一般設為Context.BIND_AUTO_CREATE。
以下建立了一個繼承Service的類,在該類中增加了幾個與繫結相關的事件方法:
public class MyFirstService extends Service{
private String info;
private MyBinder myBinder=new MyBinder();
public static final String TAG="MyFirstService";
/**
* 重新繫結時呼叫該方法
*/
@Override
public void onRebind(Intent intent) {
super.onRebind(intent);
}
/**
* 解除繫結時呼叫該方法
*/
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public IBinder onBind(Intent intent) {
return myBinder;
}
@Override
public void onCreate() {
super.onCreate();
Log.e(TAG, "--------onCreate--------");
info="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() {
super.onDestroy();
Log.e(TAG, "--------onDestroy--------");
}
public class MyBinder extends Binder{
public String getInfo(){
return info;
}
}
}
public class MainActivity extends Activity implements OnClickListener {
private Button btn_startService;
private Button btn_stopService;
private Button btn_bindService;
private Button btn_unbindService;
private Button btn_getinfo;
private Intent serviceIntent;
private MyFirstService.MyBinder myBinder;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(MyFirstService.TAG, "------onServiceDisconnected---------");
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(MyFirstService.TAG, "------onServiceConnected---------");
myBinder = (MyFirstService.MyBinder) service;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();
initEvent();
}
private void initData() {
serviceIntent = new Intent(this, MyFirstService.class);
}
private void initView() {
btn_startService = (Button) this.findViewById(R.id.btn_startService);
btn_stopService = (Button) this.findViewById(R.id.btn_stoptService);
btn_bindService = (Button) this.findViewById(R.id.btn_bindService);
btn_unbindService = (Button) this.findViewById(R.id.btn_unbindService);
btn_getinfo = (Button) this.findViewById(R.id.btn_getinfo);
}
private void initEvent() {
btn_startService.setOnClickListener(this);
btn_stopService.setOnClickListener(this);
btn_bindService.setOnClickListener(this);
btn_unbindService.setOnClickListener(this);
btn_getinfo.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_startService:// startService
startService(serviceIntent);
break;
case R.id.btn_stoptService:// stopService
stopService(serviceIntent);
break;
case R.id.btn_bindService:// bindService
bindService(serviceIntent, conn, Service.BIND_AUTO_CREATE);
break;
case R.id.btn_unbindService:// unbindService
unbindService(conn);
break;
case R.id.btn_getinfo:// 獲取資料
Toast.makeText(MainActivity.this, myBinder.getInfo(),
Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
}
執行效果:
在MyFirstService類中定義了一個MyBinder類,該類用於獲取一個String型別的返回值,
ServiceConnection.onServiceConnected方法的第2個引數是一個IBinder型別的變數,將該引數轉換成
MyFirstService.MyBinder物件,並使用myBinder.getInfo()方法獲取String型別的值。
接著看下我們是如何使用bindService和unbindService操作的。
(1)當我們單擊一次bindService(bindService(service,conn,flags))按鈕時:
(2)當我們單擊一次unbindService按鈕時:
從上面可以看出通過bindService開啟服務,再通過unbindService停止服務的過程是 onCreate------>onBind------
->onServiceConnected------->onUnbind------>onDestory
這裡面值得注意的是,當我按下home鍵時,此時並沒有呼叫unbindService方法進行停止服務,但依然能打印出
onUnbind---->onDestory,也就是說通過bindService開啟的服務是隨著Activity的銷燬而銷燬。
Service的生命週期
下圖的左半部分是通過startService()方法啟動時的Service生命週期,右半部分是通過bindService()方法啟動時
的Service生命週期。
Service生命週期有一種特殊的情形,如果Service已由某個客戶端通過startService()方法啟動了,接下來其他客
戶端再呼叫bindService()方法來繫結該Service後,再呼叫unbindService()方法解除繫結,最後又呼叫了bindService()
方法再次繫結到Service,這個過程所觸發的生命週期如下:
進行拆解步驟:
(1)呼叫startService時的生命週期:onCreate------>onStartCommand
(2)呼叫bindService時的生命週期:onBind------>onServiceConnected
(3)呼叫unbindService時的生命週期:onUnbind
(4)再一次呼叫bindService時的生命週期:onServiceConnected----->onRebind
以上呼叫unbindService時,並沒有回撥onDestroy()方法,這是因為該Service並不是由Activity通過bindService()
方法來啟動的,因此當Activity呼叫unbindService()方法取消與該Activity的繫結時,該Service也不會終止。當Activity
呼叫bindService()繫結一個已經啟動的Service時,系統只是把Service內部IBinder物件傳給Activity,當Activity呼叫
unbindService()方法取消與該Service的繫結時,只是切斷了Activity與Service之間的聯絡,並不能停止Service元件。
-------------------------------------------------------------------------------------------------------------------------------------------------------