Service
是應用程式元件,可在背景執行長時間執行的作業。不提供使用者介面。啟動後,服務可能會繼續執行一段時間,即使使用者切換至其他應用程式也是如此。此外,元件可以繫結至服務,與其互動,甚至執行跨程序通訊 (IPC)。舉例來說,服務可以處理網路交易、播放音樂、執行檔案 I/O,或與內容供應器互動,所有這些操作都會在背景執行。
注意:服務會在其代管程序的主執行緒中執行;除非您另有指定,否則服務「不會」建立自己的執行緒,也不會「在」個別程序中執行。您應在服務中的獨立執行緒上執行任何封鎖作業,以免發生應用程式無回應 (ANR) 錯誤。
服務類型
以下是三種不同類型的服務:
- 前景
-
前景服務執行的作業可為使用者察覺,舉例來說,音訊應用程式會使用前景服務播放音訊軌。前景服務必須顯示通知。即使使用者未與應用程式互動,前景服務也會繼續執行。
使用前景服務時,您必須顯示通知,讓使用者主動瞭解服務正在執行。除非服務停止執行或從前景移除,否則無法關閉這項通知。
進一步瞭解如何在應用程式中設定前景服務。
注意: WorkManager API 提供彈性的工作排程方式,可視需要將這些工作以前景服務形式執行。在許多情況下,建議使用 WorkManager 而非直接使用前景服務。
- 背景
- 背景服務執行的作業不會直接引起使用者的注意。舉例來說,如果應用程式使用服務來壓縮儲存空間,通常會是背景服務。
注意:如果應用程式指定 API 級別 26 以上版本,當應用程式本身不在前景時,系統會對執行背景服務設下限制。舉例來說,在大多數情況下,您不應在背景存取位置資訊。請改為使用 WorkManager 安排工作。
- 已綁定
- 當應用程式元件透過呼叫
bindService()
繫結至服務時,該服務就會繫結。繫結服務提供用戶端-伺服器介面,可讓元件與服務互動、傳送要求、接收結果,甚至透過處理序間通訊 (IPC) 在多個處理序之間互動。只要其他應用程式元件與繫結服務繫結,繫結服務就會執行。多個元件可以同時繫結至服務,但當所有元件都解除繫結時,服務就會遭到銷毀。
雖然本文件通常會分別討論已啟動和已繫結的服務,但您的服務可以同時以這兩種方式運作,也就是可以啟動 (無限期執行),也可以允許繫結。您只需實作幾個回呼方法:onStartCommand()
可讓元件啟動,onBind()
可允許繫結。
無論服務是否已啟動、繫結或兩者皆是,任何應用程式元件都可以使用服務 (甚至可從另一個應用程式使用),方法與任何元件使用活動的方式相同,也就是透過 Intent
啟動服務。不過,您可以在資訊清單檔案中將服務宣告為私人,並封鎖其他應用程式的存取權。如要進一步瞭解這項功能,請參閱「在資訊清單中宣告服務」一節。
選擇服務和執行緒
服務只是可在背景執行的元件,即使使用者未與應用程式互動,也能正常運作,因此請只在需要時建立服務。
如果您必須在主要執行緒外執行工作,但只在使用者與應用程式互動時執行,則應改為在其他應用程式元件的內容中建立新執行緒。舉例來說,如果您想播放音樂,但只在活動執行時播放,可以考慮在 onCreate()
中建立執行緒,在 onStart()
中開始執行,並在 onStop()
中停止執行。此外,建議您使用 java.util.concurrent
套件或 Kotlin 協同程式中的執行緒集區和執行緒,而非傳統的 Thread
類別。如要進一步瞭解如何將執行作業移至背景執行緒,請參閱「Android 的執行緒作業」說明文件。
請注意,如果您使用服務,則服務預設會在應用程式的主執行緒中執行,因此如果服務執行密集或封鎖作業,您仍應在服務中建立新執行緒。
基本概念
如要建立服務,您必須建立 Service
的子類別,或使用其中一個現有的子類別。在實作中,您必須覆寫部分回呼方法,以便處理服務生命週期的重點,並提供機制,讓元件在適當情況下綁定至服務。以下是您應覆寫的重要回呼方法:
onStartCommand()
- 當其他元件 (例如活動) 要求啟動服務時,系統會呼叫
startService()
來叫用此方法。執行這個方法時,系統會啟動服務,並可在背景無限期執行。如果您實作這項功能,就必須在工作完成後呼叫stopSelf()
或stopService()
,以便停止服務。如果您只想提供繫結,則不需要實作這個方法。 onBind()
- 當其他元件想要綁定服務 (例如執行 RPC) 時,系統會呼叫
bindService()
來叫用此方法。在實作此方法時,您必須提供介面,讓用戶端透過傳回IBinder
與服務通訊。您必須一律實作此方法;不過,如果不想允許繫結,則應傳回 null。 onCreate()
- 系統會在服務初始建立時 (在呼叫
onStartCommand()
或onBind()
之前) 叫用此方法,執行一次性設定程序。如果服務已在執行中,則不會呼叫此方法。 onDestroy()
- 當服務不再使用且即將遭到銷毀時,系統會叫用此方法。您的服務應實作這項操作,以便清理任何資源,例如執行緒、已註冊的事件監聽器或接收器。這是服務收到的最後一個呼叫。
如果元件透過呼叫 startService()
啟動服務 (導致呼叫 onStartCommand()
),服務會持續執行,直到透過 stopSelf()
停止自身,或其他元件透過呼叫 stopService()
停止服務為止。
如果元件呼叫 bindService()
來建立服務,且 onStartCommand()
未呼叫,則服務只會在元件繫結至服務時執行。服務與所有用戶端解除連結後,系統就會將其銷毀。
Android 系統只會在記憶體不足,且必須為具有使用者焦點的活動復原系統資源時,才會停止服務。如果服務已繫結至具有使用者焦點的活動,則不太可能遭到終止;如果服務已宣告為在前景執行,則幾乎不會遭到終止。如果服務已啟動且長期執行,系統會隨著時間降低其在背景工作清單中的順序,導致服務極易遭到終止。因此,如果服務已啟動,您必須設計服務,讓系統能妥善處理重新啟動作業。如果系統終止服務,會在資源可用時立即重新啟動服務,但這也取決於您從 onStartCommand()
傳回的值。如要進一步瞭解系統何時可能會毀損服務,請參閱「程序和執行緒」說明文件。
在後續章節中,您將瞭解如何建立 startService()
和 bindService()
服務方法,以及如何從其他應用程式元件使用這些方法。
在資訊清單中宣告服務
您必須在應用程式的資訊清單檔案中宣告所有服務,就像宣告活動和其他元件一樣。
如要宣告服務,請將 <service>
元素新增為 <application>
元素的子項。範例如下:
<manifest ... > ... <application ... > <service android:name=".ExampleService" /> ... </application> </manifest>
如要進一步瞭解如何在資訊清單中宣告服務,請參閱 <service>
元素參考資料。
您也可以在 <service>
元素中加入其他屬性,以定義屬性,例如啟動服務所需的權限,以及服務應執行的程序。android:name
屬性是唯一必要的屬性,可指定服務的類別名稱。發布應用程式後,請勿變更這個名稱,以免因依賴明確意圖啟動或繫結服務而導致程式碼損毀 (請參閱網誌文章「無法變更的項目」)。
注意:為確保應用程式安全,請務必在啟動 Service
時使用明確意圖,並勿為服務宣告意圖篩選器。使用隱含意圖啟動服務會危害安全性,因為您無法確定哪個服務會回應意圖,而使用者也無法查看哪個服務會啟動。自 Android 5.0 (API 級別 21) 起,如果您使用隱含意圖呼叫 bindService()
,系統會擲回例外狀況。
您可以加入 android:exported
屬性並將其設為 false
,確保服務只供您的應用程式使用。這樣一來,即使其他應用程式使用明確意圖,也無法啟動您的服務。
注意:使用者可以查看裝置上執行的服務。如果他們看到不認識或不信任的服務,可以停止該服務。為避免使用者不小心停止服務,您必須在應用程式資訊清單的 <service>
元素中加入 android:description
屬性。在說明中提供簡短句子,說明服務的用途和帶來的好處。
建立已啟動的服務
已啟動的服務是指其他元件透過呼叫 startService()
而啟動的服務,這會導致呼叫服務的 onStartCommand()
方法。
服務啟動後,其生命週期會與啟動該服務的元件無關。即使啟動服務的元件已遭到銷毀,服務仍可無限期在背景執行。因此,服務應在工作完成後呼叫 stopSelf()
來停止自身,或是由其他元件呼叫 stopService()
來停止服務。
應用程式元件 (例如活動) 可以透過呼叫 startService()
並傳遞 Intent
來啟動服務,該 Intent
會指定服務,並包含服務可使用的任何資料。服務會在 onStartCommand()
方法中接收這個 Intent
。
舉例來說,假設某個活動需要將部分資料儲存到線上資料庫,活動可以啟動隨附服務,並透過將意圖傳遞至 startService()
,將要儲存的資料傳送給該服務。服務會在 onStartCommand()
中接收意圖、連上網際網路,然後執行資料庫交易。交易完成後,服務會自動停止並遭到銷毀。
注意:服務會在與其宣告所在應用程式相同的程序中執行,並預設在該應用程式的主執行緒中執行。如果您的服務在使用者與同一個應用程式的活動互動時執行密集或封鎖作業,服務就會減緩活動效能。為避免影響應用程式效能,請在服務中啟動新執行緒。
Service
類別是所有服務的基本類別。擴充這個類別時,請務必建立服務可完成所有工作的新執行緒;服務預設會使用應用程式的主執行緒,這可能會降低應用程式執行的任何活動效能。
Android 架構也提供 Service
的 IntentService
子類別,該子類別會使用 worker 執行緒一次處理所有啟動要求。對於新應用程式,不建議使用這個類別,因為自 Android 8 Oreo 起,由於背景執行限制的引入,這個類別將無法正常運作。此外,自 Android 11 起已淘汰。您可以使用 JobIntentService 取代 IntentService
,以便與較新版本的 Android 相容。
以下各節說明如何實作您自己的自訂服務,但強烈建議您在大多數用途中改用 WorkManager。請參閱 Android 背景處理作業指南,瞭解是否有符合您需求的解決方案。
擴充 Service 類別
您可以擴充 Service
類別,以便處理每個傳入的意圖。以下是基本導入方式的樣貌:
Kotlin
class HelloService : Service() { private var serviceLooper: Looper? = null private var serviceHandler: ServiceHandler? = null // Handler that receives messages from the thread private inner class ServiceHandler(looper: Looper) : Handler(looper) { override fun handleMessage(msg: Message) { // Normally we would do some work here, like download a file. // For our sample, we just sleep for 5 seconds. try { Thread.sleep(5000) } catch (e: InterruptedException) { // Restore interrupt status. Thread.currentThread().interrupt() } // Stop the service using the startId, so that we don't stop // the service in the middle of handling another job stopSelf(msg.arg1) } } override fun onCreate() { // Start up the thread running the service. Note that we create a // separate thread because the service normally runs in the process's // main thread, which we don't want to block. We also make it // background priority so CPU-intensive work will not disrupt our UI. HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND).apply { start() // Get the HandlerThread's Looper and use it for our Handler serviceLooper = looper serviceHandler = ServiceHandler(looper) } } override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show() // For each start request, send a message to start a job and deliver the // start ID so we know which request we're stopping when we finish the job serviceHandler?.obtainMessage()?.also { msg -> msg.arg1 = startId serviceHandler?.sendMessage(msg) } // If we get killed, after returning from here, restart return START_STICKY } override fun onBind(intent: Intent): IBinder? { // We don't provide binding, so return null return null } override fun onDestroy() { Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show() } }
Java
public class HelloService extends Service { private Looper serviceLooper; private ServiceHandler serviceHandler; // Handler that receives messages from the thread private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { // Normally we would do some work here, like download a file. // For our sample, we just sleep for 5 seconds. try { Thread.sleep(5000); } catch (InterruptedException e) { // Restore interrupt status. Thread.currentThread().interrupt(); } // Stop the service using the startId, so that we don't stop // the service in the middle of handling another job stopSelf(msg.arg1); } } @Override public void onCreate() { // Start up the thread running the service. Note that we create a // separate thread because the service normally runs in the process's // main thread, which we don't want to block. We also make it // background priority so CPU-intensive work doesn't disrupt our UI. HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); // Get the HandlerThread's Looper and use it for our Handler serviceLooper = thread.getLooper(); serviceHandler = new ServiceHandler(serviceLooper); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); // For each start request, send a message to start a job and deliver the // start ID so we know which request we're stopping when we finish the job Message msg = serviceHandler.obtainMessage(); msg.arg1 = startId; serviceHandler.sendMessage(msg); // If we get killed, after returning from here, restart return START_STICKY; } @Override public IBinder onBind(Intent intent) { // We don't provide binding, so return null return null; } @Override public void onDestroy() { Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); } }
範例程式碼會處理 onStartCommand()
中的所有傳入呼叫,並將工作發布至在背景執行緒上執行的 Handler
。它的運作方式與 IntentService
相同,會依序逐一處理所有要求。舉例來說,如果您想同時執行多項要求,可以變更程式碼,在執行緒集區中執行工作。
請注意,onStartCommand()
方法必須傳回整數。整數是一種值,可說明系統在終止服務時,應如何繼續服務。onStartCommand()
的傳回值必須是下列其中一個常數:
START_NOT_STICKY
- 如果系統在
onStartCommand()
傳回後終止服務,除非有待處理的意圖要傳送,否則不要重新建立服務。這是最安全的做法,可避免在不需要時執行服務,以及應用程式可以簡單重新啟動任何未完成的工作。 START_STICKY
- 如果系統在
onStartCommand()
傳回後終止服務,請重新建立服務並呼叫onStartCommand()
,但不要重新傳送上一個意圖。相反地,除非有待處理的意圖可啟動服務,否則系統會使用空值意圖呼叫onStartCommand()
。在這種情況下,系統會傳送這些意圖。這類情況適合用於媒體播放器 (或類似服務),因為這類服務不會執行指令,但會無限期執行並等待工作。 START_REDELIVER_INTENT
- 如果系統在
onStartCommand()
傳回後終止服務,請重新建立服務,並使用傳送至服務的最後意圖呼叫onStartCommand()
。所有待處理的意圖會依序傳送。這類服務會主動執行應立即恢復的工作,例如下載檔案。
如要進一步瞭解這些傳回值,請參閱各個常數的連結參考說明文件。
啟動服務
您可以將 Intent
傳遞至 startService()
或 startForegroundService()
,從活動或其他應用程式元件啟動服務。Android 系統會呼叫服務的 onStartCommand()
方法,並傳遞 Intent
,指定要啟動的服務。
注意:如果應用程式指定的 API 級別為 26 以上,系統會對使用或建立背景服務設下限制,除非應用程式本身位於前景。如果應用程式需要建立前景服務,則應呼叫 startForegroundService()
。該方法會建立背景服務,但該方法會向系統發出信號,指出服務會將自身提升至前景。建立服務後,服務必須在五秒內呼叫其 startForeground()
方法。
舉例來說,活動可以使用含有 startService()
的明確意圖,啟動前一節的範例服務 (HelloService
),如下所示:
Kotlin
startService(Intent(this, HelloService::class.java))
Java
startService(new Intent(this, HelloService.class));
startService()
方法會立即傳回,Android 系統會呼叫服務的 onStartCommand()
方法。如果服務尚未執行,系統會先呼叫 onCreate()
,然後再呼叫 onStartCommand()
。
如果服務未提供繫結,則使用 startService()
傳送的意圖,是應用程式元件與服務之間唯一的通訊模式。不過,如果您希望服務傳回結果,啟動服務的用戶端可以使用 getBroadcast()
為廣播建立 PendingIntent
,並將其傳送至啟動服務的 Intent
。服務接著可以使用廣播來傳送結果。
啟動服務的多個要求會導致對服務的 onStartCommand()
進行多個對應呼叫。不過,只要透過 stopSelf()
或 stopService()
提出一次要求,即可停止服務。
停止服務
已啟動的服務必須自行管理生命週期。也就是說,除非必須復原系統記憶體,否則系統不會停止或銷毀服務,且服務會在 onStartCommand()
傳回後繼續執行。服務必須透過呼叫 stopSelf()
自行停止,或是其他元件可透過呼叫 stopService()
停止服務。
一旦要求使用 stopSelf()
或 stopService()
停止,系統就會盡快銷毀服務。
如果您的服務同時處理多項對 onStartCommand()
的要求,請勿在處理啟動要求後立即停止服務,因為您可能會收到新的啟動要求 (在第一個要求結束時停止服務會終止第二個要求)。為避免發生這個問題,您可以使用 stopSelf(int)
,確保停止服務的要求一律以最新的啟動要求為依據。也就是說,當您呼叫 stopSelf(int)
時,您會傳遞與停止要求相對應的開始要求 ID (傳送至 onStartCommand()
的 startId
)。接著,如果服務在您呼叫 stopSelf(int)
之前收到新的啟動要求,ID 就不會相符,且服務不會停止。
注意:為避免浪費系統資源和耗用電池電力,請務必在應用程式完成工作後停止其服務。如有需要,其他元件可以呼叫 stopService()
來停止服務。即使您為服務啟用繫結,如果服務收到 onStartCommand()
的呼叫,您仍必須自行停止服務。
如要進一步瞭解服務的生命週期,請參閱下文的「管理服務的生命週期」一節。
建立繫結服務
繫結服務可讓應用程式元件透過呼叫 bindService()
建立長期連線,以便繫結至該服務。一般來說,它不會允許元件透過呼叫 startService()
啟動。
如要透過應用程式中的活動和其他元件與服務互動,或透過進程間通訊 (IPC) 將應用程式的部分功能公開給其他應用程式,請建立繫結服務。
如要建立繫結服務,請實作 onBind()
回呼方法,以便傳回 IBinder
,該方法會定義與服務通訊的介面。其他應用程式元件接著可以呼叫 bindService()
來擷取介面,並開始呼叫服務上的方法。這項服務的生命週期只會用於服務繫結至它的應用程式元件,因此如果沒有繫結至服務的元件,系統就會將其銷毀。您不必以與透過 onStartCommand()
啟動服務時相同的方式停止已繫結的服務。
如要建立繫結服務,您必須定義介面,指定用戶端與服務的通訊方式。服務與用戶端之間的這個介面必須是 IBinder
的實作,也是服務必須從 onBind()
回呼方法傳回的內容。用戶端收到 IBinder
後,即可開始透過該介面與服務互動。
多個用戶端可以同時繫結至服務。當用戶端與服務完成互動後,就會呼叫 unbindService()
來解除繫結。如果沒有任何用戶端繫結至服務,系統會銷毀該服務。
實作繫結服務的方式有很多種,且比啟動服務更複雜。基於這些原因,我們將在另一份有關繫結服務的文件中討論繫結服務。
傳送通知給使用者
服務執行時,可以使用Snackbar 通知或狀態列通知,通知使用者事件。
Snackbar 通知是指在目前視窗表面上顯示一小段時間後就會消失的訊息。狀態列通知會在狀態列中顯示圖示和訊息,使用者可以選取圖示來執行動作 (例如啟動活動)。
一般來說,如果背景工作 (例如檔案下載作業) 已完成,使用者可以採取行動,這時使用狀態列通知是最佳做法。當使用者從展開的檢視畫面中選取通知時,通知可以啟動活動 (例如顯示已下載的檔案)。
管理服務的生命週期
服務的生命週期比活動簡單許多。不過,更重要的是,您必須密切留意服務的建立和銷毀方式,因為服務可以在使用者不知情的情況下在背景執行。
服務生命週期 (從建立到刪除) 可遵循下列任一途徑:
- 已啟動的服務
服務會在其他元件呼叫
startService()
時建立。服務會無限期執行,且必須透過呼叫stopSelf()
自行停止。其他元件也可以呼叫stopService()
來停止服務。服務停止時,系統會將其銷毀。 - 繫結服務
當其他元件 (用戶端) 呼叫
bindService()
時,系統就會建立服務。接著,用戶端會透過IBinder
介面與服務通訊。用戶端可以呼叫unbindService()
來關閉連線。多個用戶端可繫結至相同的服務,當所有用戶端都解除繫結時,系統會銷毀該服務。服務「不必」自行停止。
這兩個路徑並非完全分開。您可以繫結至已透過 startService()
啟動的服務。舉例來說,您可以呼叫 startService()
,並使用 Intent
來指定要播放的音樂,藉此啟動背景音樂服務。之後,當使用者想要對播放器進行某些控制,或取得目前歌曲的相關資訊時,活動可以透過呼叫 bindService()
來繫結至服務。在這種情況下,stopService()
或 stopSelf()
不會在所有用戶端解除綁定之前就停止服務。
實作生命週期回呼
與活動一樣,服務也有生命週期回呼方法,可讓您實作方法來監控服務狀態的變更,並在適當時間執行工作。以下骨架服務示範各個生命週期方法:
Kotlin
class ExampleService : Service() { private var startMode: Int = 0 // indicates how to behave if the service is killed private var binder: IBinder? = null // interface for clients that bind private var allowRebind: Boolean = false // indicates whether onRebind should be used override funonCreate
() { // The service is being created } override funonStartCommand
(intent: Intent?, flags: Int, startId: Int): Int { // The service is starting, due to a call to startService() return startMode } override funonBind
(intent: Intent): IBinder? { // A client is binding to the service with bindService() return binder } override funonUnbind
(intent: Intent): Boolean { // All clients have unbound with unbindService() return allowRebind } override funonRebind
(intent: Intent) { // A client is binding to the service with bindService(), // after onUnbind() has already been called } override funonDestroy
() { // The service is no longer used and is being destroyed } }
Java
public class ExampleService extends Service { int startMode; // indicates how to behave if the service is killed IBinder binder; // interface for clients that bind boolean allowRebind; // indicates whether onRebind should be used @Override public voidonCreate
() { // The service is being created } @Override public intonStartCommand
(Intent intent, int flags, int startId) { // The service is starting, due to a call tostartService()
return startMode; } @Override public IBinderonBind
(Intent intent) { // A client is binding to the service withbindService()
return binder; } @Override public booleanonUnbind
(Intent intent) { // All clients have unbound withunbindService()
return allowRebind; } @Override public voidonRebind
(Intent intent) { // A client is binding to the service withbindService()
, // after onUnbind() has already been called } @Override public voidonDestroy
() { // The service is no longer used and is being destroyed } }
注意:與活動生命週期回呼方法不同,您不必呼叫這些回呼方法的父類別實作。
圖 2 說明服務的一般回呼方法。雖然圖表將由 startService()
建立的服務與由 bindService()
建立的服務區隔開來,但請注意,無論啟動方式為何,任何服務都可能允許用戶端繫結至該服務。最初以 onStartCommand()
啟動的服務 (由用戶端呼叫 startService()
) 仍可接收對 onBind()
的呼叫 (當用戶端呼叫 bindService()
時)。
實作這些方法後,您就能監控服務生命週期的這兩個巢狀迴圈:
- 服務的整個生命週期,是指從呼叫
onCreate()
到onDestroy()
傳回之間的時間。與活動一樣,服務會在onCreate()
中執行初始設定,並在onDestroy()
中釋出所有剩餘資源。舉例來說,音樂播放服務可以在onCreate()
中建立音樂播放的執行緒,然後在onDestroy()
中停止該執行緒。注意:無論是
startService()
或bindService()
建立,系統都會為所有服務呼叫onCreate()
和onDestroy()
方法。 - 服務的有效期限會從呼叫
onStartCommand()
或onBind()
開始。每個方法都會收到傳遞至startService()
或bindService()
的Intent
。如果服務已啟動,則活動生命週期會在整個生命週期結束時結束 (即使
onStartCommand()
已傳回,服務仍會處於活動狀態)。如果服務已繫結,則在onUnbind()
傳回時,有效時間就會結束。
注意:雖然已啟動的服務會因呼叫 stopSelf()
或 stopService()
而停止,但服務並沒有相應的回呼 (沒有 onStop()
回呼)。除非服務已繫結至用戶端,否則系統會在服務停止時將其銷毀,因此您只會收到 onDestroy()
回呼。
如要進一步瞭解如何建立提供繫結功能的服務,請參閱「繫結服務」說明文件,其中的「管理繫結服務的生命週期」一節提供 onRebind()
回呼方法的詳細資訊。