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
來與服務通訊。您必須一律實作此方法;但是,如果您不想允許繫結,則應傳回空值。 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
,包括任何供服務使用的資料。服務會在 onStartCommand()
方法中收到這個 Intent
。
例如,假設某項活動需要將一些資料儲存至線上資料庫。活動可以啟動隨附服務,並將意圖傳遞至 startService()
,以傳送要儲存的資料。服務會在 onStartCommand()
中收到意圖、連線到網際網路,並執行資料庫交易。交易完成後,服務會自行停止並刪除。
注意:服務會在與應用程式相同的程序中執行,且預設會在該應用程式的主執行緒中執行。當使用者與同一應用程式中的活動互動時,如果您的服務執行密集或封鎖作業,服務會減慢活動效能。為了避免影響應用程式效能,請在服務中啟動新的執行緒。
Service
類別是所有服務的基礎類別。擴充此類別時,請務必建立新的執行緒,讓服務可在其中完成所有工作;根據預設,服務會使用應用程式的主執行緒,因此可能會降低應用程式執行的任何活動效能。
Android 架構也提供 Service
的 IntentService
子類別,使用工作站執行緒一次處理所有啟動要求。由於已引入背景執行限制,因此不建議使用這個類別用於新應用程式,因為自 Android 8 Oreo 開始,它無法正常運作。此外,自 Android 11 起也已淘汰。
您可以使用 JobIntentService 取代與新版 Android 相容的 IntentService
。
以下各節將說明如何實作自己的自訂服務,不過在大多數用途中,我們都建議您改用 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()
傳送的意圖,是應用程式元件與服務之間唯一的通訊模式。不過,如果您希望服務傳回結果,啟動服務的用戶端可以為廣播建立 PendingIntent
(使用 getBroadcast()
),並將其傳送至啟動服務的 Intent
中的服務。然後,服務就可以使用廣播來傳送結果。
多項啟動服務的要求會導致系統對服務的 onStartCommand()
發出多次對應的呼叫。不過,如要停止服務,只需要提出一次要求 (使用 stopSelf()
或 stopService()
)。
停止服務
已啟用的服務必須管理本身的生命週期。也就是說,除非必須復原系統記憶體,且服務會在 onStartCommand()
傳回後繼續執行,否則不會停止或刪除服務。服務必須藉由呼叫 stopSelf()
自行停止,或者其他元件可以透過呼叫 stopService()
將其停止。
透過 stopSelf()
或 stopService()
要求停止服務後,系統會盡快刪除服務。
如果您的服務同時處理對 onStartCommand()
的多項要求,請勿在處理啟動要求後停止服務,因為您可能已收到新的開始要求,而在第一個要求結束時停止要求,第二個要求就會終止。如要避免這個問題,您可以使用 stopSelf(int)
,確保停止服務的要求一律都是根據最近的啟動要求。也就是說,當您呼叫 stopSelf(int)
時,您會將啟動要求的 ID (傳送到 onStartCommand()
的 startId
) 傳遞給停止要求對應的 ID。然後,如果服務在您能夠呼叫 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()
啟動的服務。舉例來說,您可以透過用來識別要播放音樂的 Intent
呼叫 startService()
,啟動背景音樂服務。之後,當使用者想對播放器進行部分控制,或取得目前歌曲的相關資訊時,活動可以透過呼叫 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()
回呼方法,請參閱「管理繫結服務的生命週期」一節。