Android下的服務是在后臺運行 也是沒有界面 可以理解成是沒有界面的Activity,Android系統會為每個 應用程序創建一個進程和線程(主線程),而開啟一個服務就會創建一個進程,可以在后臺看到。
我們來分析一下進程:
? ? 進程按優先級分5中:
? ? ? ? ? 1.Foreground process 前臺進程,正在和用戶交互 相當于Activity執行了onResume方法這個進程最不容易被系統殺死。? ? ? ?
? ? ? ? ? ?2.Visible Process? 可視化進程,用戶可以看得見,但用戶不能進行交互,相當于Activity執行了onPause()方法。
? ? ? ? ? ?3.Service Process? 服務進程 , 當進程里面通過startService開啟一個服務,這時候就屬于服務進程。
? ? ? ? ? ?4. Background Process? 后臺進程, 相當于Activity執行了onStop()方法。
? ? ? ? ? ?5. Empty? Process? 空進程? ? 空進程不會維持任何運行的組件,空進程最容易被殺死,有時候它沒有被立刻殺死的目的是為下一次打開應用程序時提供打開的速度。
? ? ? ? ? 在系統運行內存不足的情況下,會檢查正在正在運行的進程,殺死優先級低的進程來騰出內存。
我們開啟服務有兩種方式: StartService()和BindService().
(a)started(啟動):當應用程序組件(如activity)調用startService()方法啟動服務時,服務處于started狀態。
? ? ? ? starService 開啟一個服務,會執行onCreate()方法,和onStart()方法,如果服務已經開啟,只會執行onStart()方法。
? ? 服務開啟后,就會在后臺長期運行,可以在設置界面找到,我們可以在設置界面手動關閉它,服務就會停止運行。
? ? ? ? startService開啟服務也叫做非綁定模式開啟服務 ,生命周期? 第一次執行的方法有 onCreate().onstartCommand(),到service關閉的時候執行onDestroy()方法。
(b)bound(綁定):當應用程序組件調用bindService()方法綁定到服務時,服務處于bound狀態。
bindService開啟服務也叫做綁定模式開啟服務,生命周期 第一次執行的方法有 onCreate(), onBind()方法,銷毀的時候執行onUnBind(),onDestroy()方法, bindService開啟服務有個特點,它在設置界面時找不到的,所以我們無法手動在設置界面銷毀它,不過它的生命周期依附于Activity,當Activity銷毀的時候,這個服務也就跟著銷毀。
??? 上面兩種生命周期實在相對單純的模式下的情形,我們在開發的過程中還必須注意Service實例只會有一個,也就是說如果當前要啟動的Service已經存在了那么就不會再次創建該Service當然也不會調用onCreate()方法;
?? 一個Service可以被多個客戶進行綁定,只有所有綁定對象都執行了unBind()方法后該Service才會銷毀,不過如果有一個用戶執行了onStart()方法,那么這個時候如果其他所有的bind客戶都執行了unBind(),該Service也不會銷毀.?很多應用都是用startService和bindService混合開啟服務,比如音樂播放器,第三方支付等
?startService()與bindService()區別:
(a)started service(啟動服務)是由其他組件調用startService()方法啟動的,這導致服務的onStartCommand()方法被調用。當服務是started狀態時,其生命周期與啟動它的組件無關,并且可以在后臺無限期運行,即使啟動服務的組件已經被銷毀。因此,服務需要在完成任務后調用stopSelf()方法停止,或者由其他組件調用stopService()方法停止。
(b)使用bindService()方法啟用服務,調用者與服務綁定在了一起,調用者一旦退出,服務也就終止,大有“不求同時生,必須同時死”的特點。
?開發人員需要在應用程序配置文件中聲明全部的service,使用標簽。
?Service通常位于后臺運行,它一般不需要與用戶交互,因此Service組件沒有圖形用戶界面。Service組件需要繼承Service基類。Service組件通常用于為其他組件提供后臺服務或監控其他組件的運行狀態。
?這時我們可能會有一個疑問:既然有StartService開啟服務,為什么還要用bindService開啟服務?
目的就是為了使用bindserivce調用服務里面的方法
這時就出現了解決進程間的通信問題:IPC,
而使用IPC就需要使用 aidl.
aidl :Android inteface defation language Android接口定義語言
使用aidl語言的步驟?
? ?[1] 有一個服務 服務里面有一個方法 ?這個方法在另外一個應用里面調用??
? ? [2]在服務的內部定義一個中間人對象(IBinder的實例)
[3]在onbind方法里面把我們定義的中間人對象返回
[4]把你想暴露的方法都定義在接口里
[5]把定義的接口Iservice.java 文件變成aidl文件 ? 注意aidl語言不認識public
? ?[6]系統會自動生產一個Iservice.java文件 ?生產一個類 stub 系統會報錯. 把我們定義的中間人對象直接繼承Stub
? ?[7]想保證2個應用程序使用的是同一個aidl文件 谷歌要求aidl文件所生成的包名要相同?
? ?[8]獲取中間人對象方式不一樣 ?是通過stub類中的一個靜態方法獲取我們定義中間人對象
[9]通過獲取到的中間人對象,調用服務里面的方法,實現IPC通信
兩種開啟服務的小demo:
public?class?MainActivity?extends?Activity?{??
private?MyConn?conn;??
@Override??
protected?void?onCreate(Bundle?savedInstanceState)?{??
super.onCreate(savedInstanceState);??
????????setContentView(R.layout.activity_main);??
? ? }??
//?點擊按鈕開啟服務??
public?void?click1(View?v)?{??
Intent?intent?=new?Intent(this,?FirstService.class);??
????????startService(intent);??
????}??
//?點擊按鈕關閉服務??
public?void?click2(View?v)?{??
Intent?intent?=new?Intent(this,?FirstService.class);??
????????stopService(intent);??
????}??
//點擊按鈕?通過bindservice?去連接服務??
public?void?click3(View?v)?{??
Intent?intent?=new?Intent(this,?FirstService.class);??
conn?=new?MyConn();??
????????bindService(intent,?conn,?BIND_AUTO_CREATE);??
? ? }??
//點擊按鈕?停止服務? ?
public?void?click4(View?v)?{??
Intent?intent?=new?Intent(this,?FirstService.class);??
????????stopService(intent);??
????}??
//當Activity銷毀的時候? ?
@Override??
protected?void?onDestroy()?{??
//取消綁定服務???
????????unbindService(conn);??
super.onDestroy();??
????}??
//監聽服務的狀態? ?
private?class?MyConn?implements?ServiceConnection{??
//當服務連接成功的時候調用??
@Override??
public?void?onServiceConnected(ComponentName?name,?IBinder?service)?{??
? ? ? ? }??
//失去連接的時候調用??
@Override??
public?void?onServiceDisconnected(ComponentName?name)?{??
? ? ? ? }??
? ? }??
}
public?class?FirstService?extends?Service?{?
?//當通過bindservice?連接成功的時候執行??
@Override??
public?IBinder?onBind(Intent?intent)?{??
System.out.println("onBind");??
return?null;??
????}??
//當service第一次創建的時候調用??
@Override??
public?void?onCreate()?{??
System.out.println("onCreate");??
super.onCreate();??
????}??
@Override??
public?int?onStartCommand(Intent?intent,?int?flags,?int?startId)?{??
System.out.println("onStartCommand");??
return?super.onStartCommand(intent,?flags,?startId);??
????}??
@Override??
public?void?onDestroy()?{??
System.out.println("onDestroy");??
super.onDestroy();??
????}??
}??
補充:(1):onstart()方法和onStartCommand()方法的區別:
onstart()方法是在android2.0一下的版本中使用。而在android2.0以上則使用onstartCommand()方法。它們兩個方法放在一起使用時,不會產生沖突。
(2):onStartComand使用時,返回的是一個(int)整形。
這個整形可以有四個返回值:start_sticky、start_no_sticky、START_REDELIVER_INTENT、START_STICKY_COMPATIBILITY。
它們的含義分別是:
1):START_STICKY:如果service進程被kill掉,保留service的狀態為開始狀態,但不保留遞送的intent對象。隨后系統會嘗試重新創建service,由于服務狀態為開始狀態,所以創建服務后一定會調用onStartCommand(Intent,int,int)方法。如果在此期間沒有任何啟動命令被傳遞到service,那么參數Intent將為null。
2):START_NOT_STICKY:“非粘性的”。使用這個返回值時,如果在執行完onStartCommand后,服務被異常kill掉,系統不會自動重啟該服務
3):START_REDELIVER_INTENT:重傳Intent。使用這個返回值時,如果在執行完onStartCommand后,服務被異常kill掉,系統會自動重啟該服務,并將Intent的值傳入。
4):START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保證服務被kill后一定能重啟。
(3)intentservice的用法
Android的Service阻塞時,通過Looper和Thread來解決標準Service中處理邏輯的阻塞問題。在android中,Service和activity是運行在同一個主線程中的。當其中的service程序出現睡眠5秒時,activity也會當機。
IntenService是service的子類,用來處理異步請求。客戶端通過startService(Intent)方法傳遞請求給IntentService,IntentService通過worker?thread處理每個intent對象,執行完后自動停止Service。
intentService需要實現兩個方法:一個構造方法,復寫一個onHandleIntent()方法。