android服務的使用
1. Android 服務的限制
Google官網將Android服務分為了三種,前台服務,後台服務和綁定服務:
前台服務執行一些用戶能注意到的操作。例如,音頻應用會使用前台服務來播放音頻曲目。前台服務必須顯示 通知 。即使用戶停止與應用的交互,前台服務仍會繼續運行。
後台服務執行用戶不會直接注意到的操作。例如,如果應用使用某個服務來壓縮其存儲空間,則此服務通常是後台服務。
當應用組件通過調用 bindService() 綁定到服務時,服務即處於 綁定 狀態。綁定服務會提供客戶端-伺服器介面,以便組件與服務進行交互、發送請求、接收結果,甚至是利用進程間通信 (IPC) 跨進程執行這些操作。僅當與另一個應用組件綁定時,綁定服務才會運行。多個組件可同時綁定到該服務,但全部取消綁定後,該服務即會被銷毀。
我個人理解服務可以分為兩種, 前台 和 後台 ,而 綁定 應該是被當作一種狀態,因為 前台服務 和 後台服務 都可以進行綁定。
基於這個理解,我們將限制分成了前台和後台兩個部分:
從 Android 5.0(API 級別 21)開始,如果使用隱式 Intent 調用 bindService() ,則系統會拋出異常。為確保應用的安全性,在啟動 Service 時,請始終使用顯式 Intent,且不要為服務聲明 Intent 過濾器。
在後台中運行的 Service 會消耗設備資源,這可能會降低用戶體驗。 為了緩解這一問題,系統對這些 Service 施加了一些限制。
處於前台時,應用可以自由創建和運行前台與後台 Service。
Android 8.0 開始:系統不允許後台應用創建後台 Service。否則該函數將引發一個 IllegalStateException。
Android 8.0 開始:進入後台時,在一個持續數分鍾的時間窗內,應用仍可以創建和使用 Service。 在該時間窗結束後,應用將被視為處於 空閑 狀態。 此時,系統將停止應用的後台 Service,就像應用已經調用 Service 的 Service.stopSelf() 方法一樣。
為了解除這種限制,可以使用 JobScheler 作業替換後台 Service。
在 Android 8.0 之前,創建前台 Service 的方式通常是先創建一個後台 Service,然後將該 Service 推到前台。
而在Android 8.0 之後,系統不允許後台應用創建後台 Service。
解決方案:調用 startForegroundService() ,以在前台啟動新 Service。
在系統創建 Service 後,應用有五秒的時間來調用該 Service 的 startForeground() 方法以顯示新 Service 的用戶可見通知。 如果應用在此時間限制內 未 調用 startForeground() ,則系統將停止此 Service 並聲明此應用為 ANR 。
前台服務必須顯示優先順序為 PRIORITY_LOW 或更高的 狀態欄通知 ,這有助於確保用戶知道應用正在執行的任務。如果某操作不是特別重要,因而您希望使用最低優先順序通知,則可能不適合使用服務;相反,您可以考慮使用 計劃作業 。
在 Android 9 (API 28)之後,使用前台服務必須申請 FOREGROUND_SERVICE 許可權,否則會報 SecurityException 。 這是普通許可權,因此,系統會自動為請求許可權的應用授予此許可權。
每個運行服務的應用都會給系統帶來額外負擔,從而消耗系統資源。如果應用嘗試使用低優先順序通知隱藏其服務,則可能會降低用戶正在主動交互的應用的性能。因此,如果某個應用嘗試運行擁有最低優先順序通知的服務,則系統會在抽屜式通知欄的底部調用出該應用的行為。
以 Android 12 為目標平台的應用在後台運行時無法再啟動 前台服務 。
在 Android 11 及以後,系統對前台服務何時可以訪問設備的位置、攝像頭或麥克風進行了限制。
如果您的應用以 Android 11 或更高版本為目標平台,且在前台服務中訪問攝像頭或麥克風,則必須添加 前台服務類型 camera 和 microphone 。
如果你的應用 在後台運行時啟動了某項前台服務 :
如果某服務的功能(位置、麥克風 和 相機)受到了限制,則Logcat中會列印如下語句:
2. android service有什麼用
Service是Android系統中的四大組件之一,它是一種長生命周期的,沒有可視化界面,運行於後台的一種服務程序。如果service是被開啟的,那麼它的活動生命周期和整個生命周期一同結束。如果service是被綁定的,它們它的活動生命周期是在onUnbind()方法返回後結束。
service積極活動的生命時間(active lifetime)是從onStartCommand()或onBind()被調用開始,它們各自處理由startService()或bindService()方法傳過來的Intent對象。
(2)android服務的使用擴展閱讀
service整體的生命時間是從onCreate()被調用開始,到onDestroy()方法返回為止。和activity一樣,service在onCreate()中進行它的初始化工作,在onDestroy()中釋放殘留的資源。
比如,一個音樂播放service可以在onCreate()中創建播放音樂的線程,在onDestory()中停止這個線程。onCreate()和onDestroy()會被所有的service調用,不論service是通過startService()還是bindService()建立。
3. 【Android】遠程服務(Remote Service)的使用
同時,在 AndroidManifest.xml 中伍滲對Remote Service進行如下配置:
在客戶端中建立與Remote Service的連接,獲取Stub,然後調用Remote Service提供的方法來獲取對應數據。
Android:關於聲猛型明文件中android:process屬性說明
【Android】枝橘猜Service那點事兒
【Android】Service前台服務的使用
4. Android使用JobService實現後台服務
前言
在Android經常要實現定時服務,定時某個時刻推送消息或者更新數據。比如需要在夜晚8:00-10:00之間,推送一條消息、彈窗、或者其他操作。
一般我們可能是開啟Service,在Service中使用AlarmManager,setRepeating定時請求,但是從API19起,並不能保證時效的准確,在5.0以後,Google推出了一個JobService,用來執行一些並非即卜桐時執行空宏的後台進程。
使用
在JobService中有兩個抽象方法onStartJob(JobParameters)和onStopJob(JobParameters)。onStartJob在JobService被調度到的時候會執行,我們只需要繼承JobService然後重寫onStartJob方法,並在裡面執行我們的後台任務就可以了。
This service executes each incoming job on a Handler running on your application's
main thread. This means that you must offload your execution logic to another
thread/handler/AsyncTask of your choosing. Not doing so will result in blocking any
future callbacks from the JobManager - specifically onStopJob(android.app.job.JobParameters), which is meant to inform you that the
scheling requirements are no longer being met.
即:JobService默認在斗弊冊主線程中處理傳入的每個操作,這意味著,你必須開一個新線
程來執行你的耗時操作,如果不這樣操作,將會阻塞來自JobManager的任何操作,特別是onStopJob操作
在Activity中,啟動服務
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
doService();
}
}
例子里可以看到,一共有五個條件,
如果我們的後台任務滿足JobService的一個或多個約束條件,就可以考慮是不是應該用JobService來執行。
5. Android TileService 使用
A TileService provides the user a tile that can be added to Quick Settings. Quick Settings is a space provided that allows the user to change settings and take quick actions without leaving the context of their current app.
tileService Api 從Android N 開始提供,用來設置app快捷設置按鈕。 如下圖示:
這個服務不需要程序開啟槐慧,系統默認能夠識別,並調用,這是一個特殊的Service,盯改在Android 7 加的,在低系統上,則不會觸發添加這個操作開關。
菜單欄中會自動添加此Tile,直接將 Tile 拖動到頂部設置欄中即可:
Google 原生系統手機是支持的,samsung OS 比較接近原生了,應該支持, MIUI 目前高版本OS也支持自定義快捷按鈕,onePlus OS 也是支持凱明判的。
這是 android N 新功能Quick Settings Tile(快速設置圖塊), 理論上各大系統廠商應該是均支持此 api 的。
參考:
6. Android 啟動後台運行程序(Service)
Android開發中,當需要創建在後台運行的程序的時候,就要使用到Service。Service 可以分為有無限生命和有限生命兩種。
特別需要注意的是Service跟Activities是不同的(簡單來說可以理解為後台與前台的區別),例如,如果需要使用Service的話,需要調用startService(),從而利用startService()去調用Service中的OnCreate()和onStart()方法來啟動一個後台的Service。
啟動一個Service的過程如下:context.startService() ->onCreate()- >onStart()->Service running其中onCreate()可以進行一些服務的初始化工作,onStart()則啟動服務。
停止一個Service的過程如下:context.stopService() | ->onDestroy() ->Service stop
接下來的實例是一個利用後台服務播放音樂的小例子,點擊start運行服務,點擊stop停止服務。ServicesDemo.java(是一個Activity)
除此之外還要在Manifest裡面聲明服務:(AndroidManifest.xml)
定義Service(MyService.java)
layout文件夾中是main.xml
values 文件夾中是strings.xm
7. Android應用組件 —— Service
官方原文: 地址
本文摘錄自官方原文,方便自己觀看。
service 是一個可以在後台長時間運行的操作而不提供用戶界面的應用組件。服務可以由其他應用組件啟動,而且即使用戶切換到其他應用程序,服務仍將在後台繼續運行。此外,組件可以綁定到服務,以與之進行交互,甚至執行進程間的通信(IPC)
服務基本分為兩種形式:
啟動
綁定
上述雖然分開概括這兩種服務,但是服務可以同時以這兩種方式運行,也就是說,他既可以是啟動服務(以無限期運行),也允許綁定。問題在於是否實現了一組回調方法: onStartCommand() (允許組件啟動服務)和 onBing() (允許綁定服務)。
無論應用是出於啟動狀態還是綁定狀態,亦或處於啟動並且綁定狀態,任何應用組件均可以像使用Activity那麼調用Itent來使用服務(即使此服務來自另一應用)。 不過,您可以通過清單文件將服務聲明為私有服務,並阻止其他應用訪問。 使用清單文件聲明服務部分將對此做更詳盡的闡述。
注意:
服務在其託管進程的主線程中運行,它既不創建自己的線程,也不在單獨的進程中運行(除非另行指定)。這意味著,如果服務將執行任何CPU密集型工作或者阻止性操作(我理解為耗時操作,例如 MP3 播放或聯網),則應在服務內創建新線程來完成這項工作。通過使用單獨的線程,可以降低發生「應用無響應」(ANR) 錯誤的風險,而應用的主線程仍可繼續專注於運行用戶與 Activity 之間的交互。
要創建服務,您必須創建 Service 的子類(或使用它的一個現有子類)。在實現中,您需要重寫一些回調方法,以處理服務生命周期的某些關鍵方面並提供一種機制將組件綁定到服務(如適用)。 應重寫的最重要的回調方法包括:
onStartCommand()
onBind()
onCreate()
onDestroy()
如果組件通過調用 startService() 啟動服務(這會導致對 onStartCommand() 的調用),則服務將一直運行,直到服務使用 stopSelf() 自行停止運行,或由其他組件通過調用 stopService() 停止它為止。
如果組件是通過調用 bindService() 來創建服務(且未調用 onStartCommand() ,則服務只會在該組件與其綁定時運行。一旦該服務與所有客戶端之間的綁定全部取消,系統便會銷毀它。
如同 Activity(以及其他組件)一樣,您必須在應用的清單文件中聲明所有服務。
要聲明服務,請添加 <service> 元素作為 <application> 元素的子元素。例如:
為了確保應用的安全性, 請始終使用顯式 Intent 啟動或綁定 Service,且不要為服務聲明 Intent 過濾器。 啟動哪個服務存在一定的不確定性,而如果對這種不確定性的考量非常有必要,則可為服務提供 Intent 過濾器並從 Intent 中排除相應的組件名稱,但隨後必須使用 setPackage() 方法設置 Intent 的軟體包,這樣可以充分消除目標服務的不確定性。
此外,還可以通過添加 android:exported 屬性並將其設置為 "false" ,確保服務僅適用於您的應用。這可以有效阻止其他應用啟動您的服務,即便在使用顯式 Intent 時也如此
Service
IntentService
簡單地說,服務是一種即使用戶未與應用交互也可在後台運行的組件。 因此,您應僅在必要時才創建服務。
如需在主線程外部執行工作,不過只是在用戶正在與應用交互時才有此需要,則應創建新線程而非服務。 例如,如果您只是想在 Activity 運行的同時播放一些音樂,則可在 onCreate() 中創建線程,在 onStart() 中啟動線程,然後在 onStop() 中停止線程。您還可以考慮使用 AsyncTask 或 HandlerThread,而非傳統的 Thread 類。
前台服務被認為是用戶主動意識到的一種服務,因此在內存不足時,系統也不會考慮將其終止。 前台服務必須為狀態欄提供通知,放在「正在進行」標題下方,這意味著除非服務停止或從前台移除,否則不能清除通知。
要請求讓服務運行於前台,請調用 startForeground() 。此方法採用兩個參數:唯一標識通知的整型數和狀態欄的 Notification 。例如:
注意 :提供給 startForeground() 的整型 ID 不得為 0。
要從前台移除服務,請調用 stopForeground() 。此方法採用一個布爾值,指示是否也移除狀態欄通知。 此方法不會停止服務。 但是,如果您在服務正在前台運行時將其停止,則通知也會被移除。
與 Activity 類似,服務也擁有生命周期回調方法,您可以實現這些方法來監控服務狀態的變化並適時執行工作。 以下框架服務展示了每種生命周期方法:
注 :與 Activity 生命周期回調方法不同,您 不 需要調用這些回調方法的超類實現。
注 :盡管啟動服務是通過調用 stopSelf() 或 stopService() 來停止,但是該服務並無相應的回調(沒有 onStop() 回調)。因此,除非服務綁定到客戶端,否則在服務停止時,系統會將其銷毀 — onDestroy() 是接收到的唯一回調。
8. 如何實現android和伺服器的長連接
轉載 這種功能實際上就是數據同步,同時要考慮手機本身、電量、網路流量等等限制因素,所以通常在移動端上有一下兩個解決方案:
1.一種是定時去server查詢數據,通常是使用HTTP協議來訪問web伺服器,稱Polling(輪詢);
2.還有一種是移動端和伺服器建立長連接,使用XMPP長連接,稱Push(推送)。
從耗費的電量、流量和數據延遲性各方面來說,Push有明顯的優勢。但是使用Push的缺點是:
對於客戶端:實現和維護相對成本高,在移動無線網路下維護長連接,相對有一些技術上的開發難度。
對於伺服器:如何實現多核並發,cpu作業調度,數量龐大的長連接並發維護等技術,仍存在開發難點。
在講述Push方案的原理前,我們先了解一下移動無線網路的特點。
移動無線網路的特點:
因為 IP v4 的 IP 量有限,運營商分配給手機凳褲終端的 IP 是運營商內網的 IP,手機要連接 Internet,就需要通過運營商的網關做一個網路地址轉換(Network Address Translation,NAT)。簡單的說運營商的網關需要維護一個外網 IP、埠到內網 IP、埠的對應關系,以確保內網的手機可以跟 Internet 的伺服器通訊
GGSN(Gateway GPRS
Support Node 網關GPRS支持結點)模塊就實現了NAT功能。
因為大部分移動無線網路運營商都是為了減少網關的NAT映射表的負荷,所以如果發現鏈路中有一段時間沒有數據通訊時,會刪除其對應表,造成鏈路中斷。(關於NAT的作用及其原理可以查看我的另一篇博文:關於使用UDP(TCP)跨區域網,NAT穿透的心得)
Push在Android平台上長連接的實現:
既然我們知道我們移動端要和Internet進行通信,必須通過運營商的網關,所以,為了不讓NAT映射表失效,我們需要定時向Internet發送數據,因為只是為了不然NAT映射表失效,所以只需發送長度為0的數據即可。
這時候就要用到定時器,在android系統上,定時器通常有一下兩種:
1.java.util.Timer
2.android.app.AlarmManager
分析:
Timer:可以按照計劃或者時間周期來執行相關的任務。但是Timer需要用WakeLock來讓CPU保持喚醒狀態,才能保證任務的執行,這樣子會消耗大量流量;當CPU處於休眠的時候,就不能喚醒執行任務,所以應用於移動端明顯是不合適。
AlarmManager:AlarmManager類是屬於android系統封裝好來管理RTC模塊的管理類。悔粗銷這里就涉及到RTC模塊,要更好地了解兩者的區別,就要明白兩者真正的區別。
RTC(Real- Time Clock)實時鬧鍾在一個嵌入式系統中,通常採用RTC
來提供可靠的系統時間,包括時分秒和年月日等;而且要求在系統處於關碧游機狀態下它也能夠正常工作(通常採用後備電池供電),它的外圍也不需要太多的輔助電路,典型的就是只需要一個高精度的32.768KHz
晶體和電阻電容等。(如果對這方面感興趣,可以自己查閱相關資料,這里就說個大概)
好了,回來正題。所以,AlarmManager又稱全局定時鬧鍾。這意味著,當我用使用AlarmManager來定時執行任務,CPU可以正常地休眠,只有在執行任務是,才喚醒CPU,這個過程是很短時間的。
下面簡單來說明其使用:
1.類似於Timer功能:
//獲得鬧鍾管理器
AlarmManager
am = (AlarmManager)getSystemService(ALARM_SERVICE);
//設置任務執行計劃
am.setRepeating(AlarmManager.ELAPSED_REALTIME, firstTime, 5*1000,
sender);//從firstTime才開始執行,每隔5秒再執行
2.實現全局定時功能:
//獲得鬧鍾管理器
AlarmManager
am = (AlarmManager)getSystemService(ALARM_SERVICE);
//設置任務執行計劃
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime,
5*1000, sender);//從firstTime才開始執行,每隔5秒再執行
總結:在android客戶端使用Push推送時,應該使用AlarmManager來實現心跳功能,使其真正實現長連接。