一. Service簡介
1.1 Service簡介:
- Android四大組件之一,中文名叫“服務(wù)”。
- 屬于Android中的計算型組件,作用是執(zhí)行一些需要長期運行的操作,如復(fù)雜計算和后臺下載等。
- 特點是長生命周期、在后臺允許、沒有用戶界面。
1.2 Service分類:
- 運行地點分類:本地服務(wù)和遠程服務(wù)
- 運行類型分類:前臺服務(wù)和后臺服務(wù)
- 功能類型分類:可通信和不可通信
二. Service使用
Service有兩種啟動方式,分別為context.startService()和context.bindService()。這里要提到Service的生命周期,兩種不同的啟動方式有不同的生命周期:

簡單介紹:
- 調(diào)用startService方法,Service會經(jīng)歷onCreate()創(chuàng)建、onStartCommand()開始運行、接著便進入running階段。此時,如果再調(diào)用startService()方法,不會創(chuàng)建新的Service對象,系統(tǒng)會自動調(diào)用原來的Service實例。如果該Service被stopService()或者其它方式來停止運行,會執(zhí)行onDestory()之后便停止該服務(wù),無論之前調(diào)用過多少次startService()都會被銷毀。
- 使用bindService()方法,系統(tǒng)首先創(chuàng)建一個Service實例,接著調(diào)用 onCreate()、onBind(),之后調(diào)用者就可以跟服務(wù)進行交互。使用unbindService()方法來解除綁定,此時onUnbind()方法和onDestroy()方法相繼調(diào)用,停止服務(wù)。
Tips:
- startService()啟動的服務(wù),其調(diào)用者的生命周期與Service的生命周期沒有必然聯(lián)系,即使調(diào)用者的生命周期結(jié)束了,Service依舊在運行,除非調(diào)用stopService()來停止服務(wù)。
- bindService()啟動的服務(wù),服務(wù)與調(diào)用者的生命周期是綁定的,一旦調(diào)用者退出,服務(wù)也隨著停止。
- startService()方式啟動的服務(wù),調(diào)用者不可與Service()進行交互,而bindService()啟動可以進行交互。
2.1 具體使用: .startService()
首先創(chuàng)建自己的Service類,重寫其生命周期,并在mainfest.xml中進行注冊。
public class TestService extends Service {
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
必須注冊Service,不然不會調(diào)用。簡單注冊:
<service
android:name=".service.TestService">
</service>
補充下Service在manifest中的屬性以及作用:
| 屬性 | 說明 | 備注 |
|---|---|---|
| android:name | Service類名 | |
| android:label | Service標簽(名字) | 默認為Service類名 |
| android:icon | Service圖標 | |
| android:permission | 此Service權(quán)限 | 提供了該權(quán)限的應(yīng)用才能控制或連接此服務(wù) |
| android:process | 表示該服務(wù)是否在另一個進程中運行(遠程服務(wù)) | 不設(shè)置默認為本地服務(wù);remote則設(shè)置成遠程服務(wù) |
| android:enabled | 系統(tǒng)默認啟動 | true:Service 將會默認被系統(tǒng)啟動;不設(shè)置則默認為false |
| android:exported | 該服務(wù)是否能夠被其他應(yīng)用程序所控制或連接 | 不設(shè)置默認此項為 false |
接下來,我們就可以用下面的兩個方法來啟動和停止服務(wù)。
// 啟動服務(wù)
public void start() {
Intent intent = new Intent(this, TestService.class);
startService(intent);
}
// 停止服務(wù)
public void stop() {
Intent intent = new Intent(this, TestService.class);
stopService(intent);
}
2.2 具體使用: .bindService()
首先在我們的Activity中創(chuàng)建Service連接對象,重寫連接和斷開的方法。創(chuàng)建自定義的Binder對象,在onServiceConnected()中賦值然后可以調(diào)用自定義Binder中的方法。使用下方的bind()方法來綁定服務(wù),使用unBind()來解綁服務(wù)。
public class TestActivity extends AppCompatActivity {
// Service中自定義的Binder對象
private TestService.MyBinder myBinder;
// 創(chuàng)建一個Service連接對象
private ServiceConnection serviceConnection = new ServiceConnection() {
// Service連接時調(diào)用
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
// 使用向下轉(zhuǎn)型來給myBinder賦值,然后可以調(diào)用自定義Binder中的方法
myBinder = (TestService.MyBinder) iBinder;
myBinder.service_connect_Activity();
}
// Service斷開連接或異常丟失連接時調(diào)用
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
/**
* 綁定服務(wù)
*/
private void bind(){
Intent intent = new Intent(this, TestService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
/**
* 解綁服務(wù)
*/
private void unBind(){
unbindService(serviceConnection);
}
}
這里會用到Service的onBind()和onUnbind()的生命周期,我們在TestService中重寫之。這里要注意的是,使用bindService()方法啟動的Service,不會調(diào)用onStartCommand()的生命周期。此外,創(chuàng)建自定義Binder類和對象。
public class TestService extends Service {
private MyBinder mBinder = new MyBinder();
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
}
//新建一個子類繼承自Binder類
class MyBinder extends Binder {
// service和Activity連接用
public void service_connect_Activity() {
Log.i("tag","Activity調(diào)用Service,并成功調(diào)用此方法。");
}
}
}
這樣,當我們使用Activity中的bind()方法來綁定服務(wù),會自動啟動服務(wù),而我們又重寫了onServiceConnected()方法并使用myBinder來調(diào)用方法。這樣我們就可以用它來Activity和Service來進行通信。
特別Tips:
如果先使用startService()來開啟服務(wù)和bindService()來綁定服務(wù),當使用unbindService()解綁時,Service并不會被銷毀。而是使用stopService()才能銷毀服務(wù)。
2.3 前臺服務(wù):
前臺服務(wù)和后臺服務(wù)的區(qū)別:
- 前臺服務(wù)會在通知欄顯示通知,而后臺服務(wù)沒有。
- 前臺服務(wù)優(yōu)先級較高,不會在系統(tǒng)內(nèi)存不足時被回收,而后臺服務(wù)會被回收。
2.3.1具體使用:
在Service中進行操作,將服務(wù)類型以前臺的方式運行顯示在通知欄。
@Override
public void onCreate() {
super.onCreate();
// 創(chuàng)建Intent,跳轉(zhuǎn)到指定的類
Intent notificationIntent = new Intent(this,TestActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,notificationIntent,0);
Notification.Builder builder = new Notification.Builder(this);
builder.setContentTitle("前臺服務(wù)標題"); // 設(shè)置標題
builder.setContentText("前臺服務(wù)內(nèi)容"); // 設(shè)置內(nèi)容
builder.setSmallIcon(R.mipmap.ic_launcher); // 設(shè)置圖標
builder.setContentIntent(pendingIntent); // 設(shè)置點擊跳轉(zhuǎn)后的intent
Notification notification = builder.getNotification(); // builder獲取Notification對象
startForeground(1,notification); // 開啟前臺服務(wù),第一個參數(shù)為id
}
運行效果:

2.4 遠程服務(wù):
暫時引用吧,有空再實現(xiàn)一個:
三.總結(jié)一下各類Service的特性和使用場景:
- 按運行地點分類:
| 類別 | 特點 | 優(yōu)點 | 缺點 | 應(yīng)用場景 |
|---|---|---|---|---|
| 本地服務(wù)(Local) | 運行在主線程 | 節(jié)約資源、方便通信 | 限制性大,依賴主進程運行 | 依附某個進程進行服務(wù),如音樂播放 |
| 遠程服務(wù)(Remote) | 運行在獨立進程,常駐后臺,不受其它Activity影響 | 比較靈活,不太受約束 | 消耗資源(單獨進程)、使用復(fù)雜(AIDL IPC) | 系統(tǒng)級別服務(wù) |
- 按運行類型分類:
| 類別 | 特點 | 應(yīng)用場景 |
|---|---|---|
| 前臺服務(wù)(forceground) | 在通知欄顯示(用戶可以看到) | 使用時需要讓用戶了解并能進行操作,如通知欄音樂播放(終止服務(wù),通知欄橫幅消失) |
| 后臺服務(wù)(background) | 后臺運行 | 使用時無需讓用戶知道和操作,如更新天氣,計時提醒等。(終止服務(wù),用戶無法知道) |
- 按功能分類:
| 類別 | 特點 | 應(yīng)用場景 |
|---|---|---|
| 不可通信的后臺服務(wù) | startService()啟動,退出后service仍然運行 | 在后臺運行不進行通信 |
| 可通信的后臺服務(wù) | bindService()啟動,不執(zhí)行onStartCommand(),隨著調(diào)用者銷毀 | 該后臺服務(wù)需要進行通信 |
參考資料:
基礎(chǔ)總結(jié)篇之四:Service完全解析
Android四大組件:Service服務(wù)史上最全面解析