前景服務執行的是使用者察覺的作業。
前景服務會顯示狀態列 通知,提醒使用者 應用程式正在前景執行工作並消耗系統資源。
以下列舉使用前景服務的應用程式:
- 音樂播放器應用程式在前景服務中播放音樂,通知 可能會顯示目前播放的歌曲
- 當使用者在前景服務中記錄跑步的健身應用程式,之後 徵得使用者的許可通知可能會顯示距離 使用者在目前的健身工作階段中所走過的距離。
只在應用程式需要執行工作時,才使用前景服務 但就算使用者並未直接與 互動 應用程式如果動作的重要性太低,您想要使用 建立背景為「最低優先順序」的通知 工作。
本文件說明瞭使用前景服務的必要權限。 以及如何啟動前景服務,以及如何從背景移除這類服務。此外, 說明如何將特定用途與前景服務類型建立關聯。 啟動前景服務後生效的存取權限制 從在背景執行的應用程式開始篩選
使用者預設能關閉通知
從 Android 13 (API 級別 33) 開始,使用者可以關閉通知 已與前景服務建立關聯使用者只要滑動螢幕即可 手勢。一般來說 除非前景服務停止或移除,否則不會關閉 從前景開始。
若您希望使用者不要關閉通知,請
true
加入setOngoing()
方法。Notification.Builder
立即顯示通知的服務
如果前景服務具備至少下列其中一項特性,則 系統會在服務啟動後立即顯示相關的通知 包括:
- 服務會與含有動作動作的通知 按鈕。
- Service 有
foregroundServiceType
敬上 /mediaPlayback
,mediaProjection
,或phoneCall
。 - 這項服務提供與通話、導航或媒體相關的用途 如通知的類別所定義 屬性。
- 服務透過傳遞
FOREGROUND_SERVICE_IMMEDIATE
加入setForegroundServiceBehavior()
。
在 Android 13 (API 級別 33) 以上版本中,如果使用者拒絕 通知權限、 使用者仍會在 工作管理員 但無法在通知導覽匣中查看
在資訊清單中宣告前景服務
在應用程式的資訊清單中,宣告應用程式的各項前景服務
使用 <service>
元素。針對每個服務,使用
android:foregroundServiceType
屬性
宣告服務的工作類型
舉例來說,如果您的應用程式建立了播放音樂的前景服務, 可能會宣告服務如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>
<application ...>
<service
android:name=".MyMediaPlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="false">
</service>
</application>
</manifest>
如果服務符合多種類型,請使用 |
加以分隔
運算子。例如使用攝影機和麥克風的服務
宣告方式如下:
android:foregroundServiceType="camera|microphone"
要求前景服務權限
指定 Android 9 (API 級別 28) 以上版本且使用前景服務的應用程式
必須先要求
FOREGROUND_SERVICE
敬上
,如以下程式碼片段所示。這是正常現象
權限,因此系統
會自動授予提出要求的應用程式。
此外,如果應用程式指定 API 級別 34 或以上級別,就必須請求
適當權限類型,說明前景服務會針對何種工作類型執行相應權限
表現如何。每種前景服務類型
都有相對應的權限類型舉例來說,如果應用程式啟動
使用相機的前景服務,必須同時要求
FOREGROUND_SERVICE
敬上
和 FOREGROUND_SERVICE_CAMERA
授予其要求的權限。這些都是一般權限,因此系統會授予這些權限
。
<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA"/>
<application ...>
...
</application>
</manifest>
前景服務必要條件
從 Android 14 (API 級別 34) 開始,當您啟動前景服務時。
系統會根據服務類型,檢查是否有特定的必要條件。例如:
如果您嘗試啟動 location
類型的前景服務,系統會檢查
請確認您的應用程式已有 ACCESS_COARSE_LOCATION
或
ACCESS_FINE_LOCATION
權限。否則,系統會擲回
SecurityException
。
因此,請務必確認您符合必要條件 啟動前景服務之前。前景服務 type 說明文件 列出每種前景服務類型必備的必要條件。
啟動前景服務
如要要求系統以前景服務形式執行服務,請先啟動 服務本身:
Kotlin
val intent = Intent(...) // Build the intent for the service context.startForegroundService(intent)
Java
Context context = getApplicationContext(); Intent intent = new Intent(...); // Build the intent for the service context.startForegroundService(intent);
在服務中 (通常為 onStartCommand()
),您可以要求
您的服務會在前景執行。方法是呼叫
ServiceCompat.startForeground()
敬上
(適用於 androidx-core 1.12 以上版本)。這個方法需要下列項目
參數:
- 「服務」
- 可在狀態列中識別通知的唯一正整數
Notification
物件本身- 前景服務類型 識別服務執行的作業
這些類型可能是資訊清單中宣告的類型的子集。
視特定用途而定如果您需要新增更多服務類型
您可以再次呼叫 startForeground()
。
舉例來說,假設某個健身應用程式提供的跑步追蹤服務始終是
需要location
資訊,但不一定需要播放媒體。個人中心
您需要在資訊清單中宣告 location
和 mediaPlayback
。如果
使用者開始跑步,且只希望追蹤他們的位置。您的應用程式應該呼叫
startForeground()
,並僅傳遞 ACCESS_FINE_LOCATION
權限。接著:
如果使用者想開始播放音訊,請再次呼叫 startForeground()
,然後
傳遞所有前景服務類型的位元組合 (在本例中為
ACCESS_FINE_LOCATION|FOREGROUND_SERVICE_MEDIA_PLAYBACK
)。
以下範例說明如何啟動相機前景服務:
Kotlin
class MyCameraService: Service() { private fun startForeground() { // Before starting the service as foreground check that the app has the // appropriate runtime permissions. In this case, verify that the user has // granted the CAMERA permission. val cameraPermission = PermissionChecker.checkSelfPermission(this, Manifest.permission.CAMERA) if (cameraPermission != PermissionChecker.PERMISSION_GRANTED) { // Without camera permissions the service cannot run in the foreground // Consider informing user or updating your app UI if visible. stopSelf() return } try { val notification = NotificationCompat.Builder(this, "CHANNEL_ID") // Create the notification to display while the service is running .build() ServiceCompat.startForeground( /* service = */ this, /* id = */ 100, // Cannot be 0 /* notification = */ notification, /* foregroundServiceType = */ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA } else { 0 }, ) } catch (e: Exception) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && e is ForegroundServiceStartNotAllowedException) { // App not in a valid state to start foreground service // (e.g. started from bg) } // ... } } }
Java
public class MyCameraService extends Service { private void startForeground() { // Before starting the service as foreground check that the app has the // appropriate runtime permissions. In this case, verify that the user // has granted the CAMERA permission. int cameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA); if (cameraPermission == PackageManager.PERMISSION_DENIED) { // Without camera permissions the service cannot run in the // foreground. Consider informing user or updating your app UI if // visible. stopSelf(); return; } try { Notification notification = new NotificationCompat.Builder(this, "CHANNEL_ID") // Create the notification to display while the service // is running .build(); int type = 0; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { type = ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA; } ServiceCompat.startForeground( /* service = */ this, /* id = */ 100, // Cannot be 0 /* notification = */ notification, /* foregroundServiceType = */ type ); } catch (Exception e) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && e instanceof ForegroundServiceStartNotAllowedException ) { // App not in a valid state to start foreground service // (e.g started from bg) } // ... } } //... }
從前景移除服務
如要從前景移除服務,請呼叫
stopForeground()
。
這個方法會採用布林值,指出是否要移除狀態列
通知請注意,服務會繼續執行。
如果服務在前景執行時停止,該服務會收到通知 就會遭到移除
處理使用者啟動的前景服務應用程式停止作業
從 Android 13 (API 級別 33) 開始,使用者可以從 通知導覽匣 停止執行持續運作的前景服務的應用程式,無論該應用程式的 目標 SDK 版本這種預設用途稱為 工作管理員,顯示 執行前景服務
這份清單會標示為「有效的應用程式」。 每個應用程式旁邊都有一個「停止」按鈕。圖 1 說明瞭 在執行的裝置上,工作管理員工作流程 Android 13.
當使用者在 工作管理員,然後執行下列操作:
- 系統會從記憶體中移除應用程式。因此,「整個應用程式」都會停止運作 而不只是執行中的前景服務
- 系統會移除應用程式的活動返回堆疊。
- 所有媒體播放作業都會停止,
- 系統會移除與前景服務相關聯的通知。
- 應用程式仍會留在記錄中。
- 已排定的工作會在排定時間執行。
- 鬧鐘會在排定的時間或時間範圍響起。
在使用者停止應用程式期間和結束後,測試應用程式是否正常運作 應用程式,在終端機視窗中執行下列 ADB 指令:
adb shell cmd activity stop-app PACKAGE_NAME
豁免資格
系統會為特定類型的應用程式提供幾種豁免層級; 以下各節將說明。
豁免資格因應用程式而異,而非個別程序。如果系統在 應用程式中的所有其他程序也不受限制。
豁免於工作管理員
以下應用程式可執行前景服務,但不會顯示在 工作管理員:
- 系統層級應用程式
- 安全應用程式;這表示具有
ROLE_EMERGENCY
角色 - 中的裝置 示範模式
使用者無法停止豁免
當下列類型的應用程式執行前景服務時,它們會顯示在 工作管理員,但任務管理員旁邊沒有「Stop」按鈕 使用者輕觸的應用程式名稱:
- 裝置擁有者應用程式
- 設定檔擁有者 應用程式
- 永久應用程式
- 具備
ROLE_DIALER
角色
使用專為特定用途建立的 API,而非前景服務
在許多用途中,您可以透過平台或 Jetpack API 完成工作 也可以將前景服務用於這類用途如有需要 在大部分的情況下,您應一律使用這個 API 取代前景 課程中也會快速介紹 Memorystore 這是 Google Cloud 的全代管 Redis 服務專為特定用途設計的 API 通常會提供其他特定用途 必須自行建構的功能例如: Bubbles API 會處理複雜的 UI 邏輯 需要實作聊天對話框功能的訊息應用程式。
前景服務類型說明文件 建議使用而非前景服務。
從背景啟動前景服務的限制
指定 Android 12 以上版本的應用程式無法啟動前景
服務,但少部分特殊權限和
案件如果應用程式嘗試啟動
應用程式在背景執行期間的前景服務
不符合其中一個例外情況時,系統就會擲回
ForegroundServiceStartNotAllowedException
。
此外,如果應用程式想要啟動需要前景服務 使用期間權限 (例如人體感應器、相機、麥克風或 地點 則無法在背景執行時「建立」服務。 即使應用程式不受背景啟動限制 以及請參閱「 啟動需要在使用中的前景服務 權限。
不受背景啟動限制的限制
在下列情況下,您的應用程式即使在 應用程式會在背景執行:
- 應用程式會從使用者可見的狀態轉換,例如 活動。
- 您的應用程式可以從以下位置啟動活動: 背景 (這種情況除外) 應用程式在現有工作的返回堆疊中有活動。
應用程式透過 Firebase Cloud 收到高優先順序訊息 訊息。
應用程式會叫用精確鬧鐘, 完成使用者要求的動作
您的應用程式是裝置目前的輸入來源 方法。
裝置重新啟動並收到
ACTION_BOOT_COMPLETED
、ACTION_LOCKED_BOOT_COMPLETED
, 或ACTION_MY_PACKAGE_REPLACED
廣播接收器中的意圖動作。應用程式收到
ACTION_TIMEZONE_CHANGED
、ACTION_TIME_CHANGED
, 或ACTION_LOCALE_CHANGED
意圖動作。應用程式收到
ACTION_TRANSACTION_DETECTED
敬上 「NfcService
」的活動。應用程式使用隨附裝置管理工具,並宣告
REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND
敬上 權限或REQUEST_COMPANION_RUN_IN_BACKGROUND
權限。盡可能使用REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND
。您的應用程式會保留
SYSTEM_ALERT_WINDOW
敬上 權限。使用者關閉應用程式的電池效能最佳化功能。
限制啟動需要在使用期間權限的前景服務
在 Android 14 (API 級別 34) 以上版本中,有特殊情況需要留意。 。
如果應用程式指定 Android 14 或以上版本為目標,則作業系統
檢查何時建立前景服務,確保應用程式具備
授予該服務類型的適當權限舉例來說,假設您建立
類型的前景服務
microphone、
系統會驗證您的應用程式目前是否
RECORD_AUDIO
敬上
權限。如果您沒有這項權限,系統會擲回
SecurityException
。
如果具備使用中權限,可能會造成潛在問題。如果你的應用程式有
使用期間的權限,只有在位於
前景。也就是說,如果您的應用程式是在背景執行,且嘗試建立
相機、位置或麥克風類型的前景服務,系統會偵測
您的應用程式目前未具備必要權限,且
SecurityException
。
同樣地,如果您的應用程式在背景執行,且會建立
需要 BODY_SENSORS_BACKGROUND
權限的健康服務,應用程式
目前還沒有這項權限,因此系統會擲回例外狀況。
(如果健康服務需要其他權限,則不適用這個情況;
例如「ACTIVITY_RECOGNITION
」。) 撥打電話
PermissionChecker.checkSelfPermission()
「無法」防止這個問題。如果您的應用程式有使用期間的權限,且
它會呼叫 checkSelfPermission()
,檢查是否具備該權限
即使應用程式是在背景執行,仍會傳回 PERMISSION_GRANTED
。當
方法會傳回 PERMISSION_GRANTED
,表示「您的應用程式具備這項權限」
「在應用程式使用期間」。」
因此,如果您的前景服務需要單次使用權限,
必須在以下時間內呼叫 Context.startForegroundService()
或 Context.bindService()
除非服務屬於下列任一類別,否則應用程式應有可見活動
定義豁免情況。
不受使用時權限限制
在某些情況下,即使在應用程式啟動時啟動前景服務也一樣 跑步 在背景存取位置資訊,仍可存取位置資訊 應用程式在前景執行時,相機和麥克風資訊 (「使用期間」)。
在這種情況下,如果服務宣告了
前景服務類型為 location
的應用程式,並透過以下應用程式啟動:
具有
ACCESS_BACKGROUND_LOCATION
。
允許這項服務隨時存取位置資訊,即使
應用程式會在背景執行
下方清單列出下列情況:
- 系統元件會啟動服務。
- 服務首先會與應用程式互動 小工具。
- 服務首先與通知互動。
- 這項服務一開始是
PendingIntent
會從 不同的可見應用程式 - 服務啟動時是由裝置政策的應用程式啟動 控制器。
- 服務是由提供
VoiceInteractionService
的應用程式啟動。 - 服務由具備
START_ACTIVITIES_FROM_BACKGROUND
特殊權限。
判斷哪些服務會在應用程式中受到影響
在測試應用程式時,啟動其前景服務。如果已啟動的服務 已限制存取位置資訊、麥克風和相機,以下訊息 出現在 Logcat 中:
Foreground service started from background can not have \ location/camera/microphone access: service SERVICE_NAME