Для запуска службы переднего плана из вашего приложения нужно выполнить два шага. Во-первых, вы должны запустить службу, вызвав context.startForegroundService()
. Затем служба должна вызвать ServiceCompat.startForeground()
чтобы перевести себя в службу переднего плана.
Предпосылки
В зависимости от того, на какой уровень API ориентировано ваше приложение, существуют некоторые ограничения на то, когда приложение может запускать службу переднего плана.
Приложения, ориентированные на Android 12 (уровень API 31) или выше, не могут запускать службу переднего плана, пока приложение находится в фоновом режиме, за несколькими конкретными исключениями. Для получения дополнительной информации и информации об исключениях из этого правила см. Ограничения на запуск службы переднего плана из фонового режима .
Приложения, предназначенные для Android 14 (уровень API 34) или выше, должны запрашивать соответствующие разрешения для типа службы переднего плана. Когда приложение пытается перевести службу на передний план, система проверяет наличие соответствующих разрешений и выдает исключение
SecurityException
, если приложение их не имеет. Например, если вы пытаетесь запустить службу переднего плана типаlocation
, система проверяет, есть ли у вашего приложения разрешениеACCESS_COARSE_LOCATION
илиACCESS_FINE_LOCATION
. В документации по типу службы переднего плана перечислены необходимые предварительные условия для каждого типа службы переднего плана.
Запустить услугу
Чтобы запустить службу переднего плана, необходимо сначала запустить ее как обычную (не приоритетную) службу:
Котлин
val intent = Intent(...) // Build the intent for the service context.startForegroundService(intent)
Ява
Context context = getApplicationContext(); Intent intent = new Intent(...); // Build the intent for the service context.startForegroundService(intent);
Ключевые моменты кодекса
- Фрагмент кода запускает службу. Однако служба пока не запущена на переднем плане. Внутри самой службы необходимо вызвать
ServiceCompat.startForeground()
, чтобы перевести службу в режим переднего плана.
Вывести услугу на передний план
После запуска службы вам необходимо вызвать ServiceCompat.startForeground()
чтобы запросить запуск службы на переднем плане. Обычно вы вызываете этот метод в методе onStartCommand()
службы.
ServiceCompat.startForeground()
принимает следующие параметры:
- Обслуживание.
- Положительное целое число, которое однозначно идентифицирует уведомление службы в строке состояния.
- Сам объект
Notification
. - Тип или типы приоритетной службы, идентифицирующие работу, выполняемую службой
Типы служб переднего плана, которые вы передаете в startForeground()
объявляются в манифесте в зависимости от конкретного варианта использования. Затем, если вам нужно добавить больше типов служб, вы можете снова вызвать startForeground()
.
Например, предположим, что фитнес-приложение запускает службу отслеживания бега, которой всегда нужна информация location
, но может потребоваться или не потребоваться воспроизведение медиа. Вам нужно будет объявить и location
, и mediaPlayback
в манифесте. Если пользователь начинает пробежку и просто хочет, чтобы его местоположение отслеживалось, ваше приложение должно вызвать startForeground()
и передать только разрешение ACCESS_FINE_LOCATION
. Затем, если пользователь хочет начать воспроизведение аудио, снова вызовите startForeground()
и передайте побитовую комбинацию всех типов служб переднего плана (в данном случае ACCESS_FINE_LOCATION|FOREGROUND_SERVICE_MEDIA_PLAYBACK
).
В следующем примере показан код, который служба камеры будет использовать для перехода в режим переднего плана:
Котлин
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) } // ... } } }
Ява
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) } // ... } } //... }
Ключевые моменты кодекса
- Приложение уже заявило в манифесте, что ему необходимо разрешение
CAMERA
. Однако приложение также должно проверить во время выполнения, чтобы убедиться, что пользователь предоставил это разрешение. Если у приложения на самом деле нет правильных разрешений, оно должно сообщить пользователю о проблеме. - Различные типы служб переднего плана были введены с различными версиями платформы Android. Этот код проверяет, на какой версии Android он запущен, и запрашивает соответствующие разрешения.
- Код проверяет наличие исключения
ForegroundServiceStartNotAllowedException
в случае, если он пытается запустить службу переднего плана в ситуации, которая недопустима (например, если он пытается перевести службу на передний план , пока приложение находится в фоновом режиме ).
Для запуска службы переднего плана из вашего приложения нужно выполнить два шага. Во-первых, вы должны запустить службу, вызвав context.startForegroundService()
. Затем служба должна вызвать ServiceCompat.startForeground()
чтобы перевести себя в службу переднего плана.
Предпосылки
В зависимости от того, на какой уровень API ориентировано ваше приложение, существуют некоторые ограничения на то, когда приложение может запускать службу переднего плана.
Приложения, ориентированные на Android 12 (уровень API 31) или выше, не могут запускать службу переднего плана, пока приложение находится в фоновом режиме, за несколькими конкретными исключениями. Для получения дополнительной информации и информации об исключениях из этого правила см. Ограничения на запуск службы переднего плана из фонового режима .
Приложения, предназначенные для Android 14 (уровень API 34) или выше, должны запрашивать соответствующие разрешения для типа службы переднего плана. Когда приложение пытается перевести службу на передний план, система проверяет наличие соответствующих разрешений и выдает исключение
SecurityException
, если приложение их не имеет. Например, если вы пытаетесь запустить службу переднего плана типаlocation
, система проверяет, есть ли у вашего приложения разрешениеACCESS_COARSE_LOCATION
илиACCESS_FINE_LOCATION
. В документации по типу службы переднего плана перечислены необходимые предварительные условия для каждого типа службы переднего плана.
Запустить услугу
Чтобы запустить службу переднего плана, необходимо сначала запустить ее как обычную (не приоритетную) службу:
Котлин
val intent = Intent(...) // Build the intent for the service context.startForegroundService(intent)
Ява
Context context = getApplicationContext(); Intent intent = new Intent(...); // Build the intent for the service context.startForegroundService(intent);
Ключевые моменты кодекса
- Фрагмент кода запускает службу. Однако служба пока не запущена на переднем плане. Внутри самой службы необходимо вызвать
ServiceCompat.startForeground()
, чтобы перевести службу в режим переднего плана.
Вывести услугу на передний план
После запуска службы вам необходимо вызвать ServiceCompat.startForeground()
чтобы запросить запуск службы на переднем плане. Обычно вы вызываете этот метод в методе onStartCommand()
службы.
ServiceCompat.startForeground()
принимает следующие параметры:
- Обслуживание.
- Положительное целое число, которое однозначно идентифицирует уведомление службы в строке состояния.
- Сам объект
Notification
. - Тип или типы приоритетной службы, идентифицирующие работу, выполняемую службой
Типы служб переднего плана, которые вы передаете в startForeground()
объявляются в манифесте в зависимости от конкретного варианта использования. Затем, если вам нужно добавить больше типов служб, вы можете снова вызвать startForeground()
.
Например, предположим, что фитнес-приложение запускает службу отслеживания бега, которой всегда нужна информация location
, но может потребоваться или не потребоваться воспроизведение медиа. Вам нужно будет объявить и location
, и mediaPlayback
в манифесте. Если пользователь начинает пробежку и просто хочет, чтобы его местоположение отслеживалось, ваше приложение должно вызвать startForeground()
и передать только разрешение ACCESS_FINE_LOCATION
. Затем, если пользователь хочет начать воспроизведение аудио, снова вызовите startForeground()
и передайте побитовую комбинацию всех типов служб переднего плана (в данном случае ACCESS_FINE_LOCATION|FOREGROUND_SERVICE_MEDIA_PLAYBACK
).
В следующем примере показан код, который служба камеры будет использовать для перехода в режим переднего плана:
Котлин
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) } // ... } } }
Ява
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) } // ... } } //... }
Ключевые моменты кодекса
- Приложение уже заявило в манифесте, что ему необходимо разрешение
CAMERA
. Однако приложение также должно проверить во время выполнения, чтобы убедиться, что пользователь предоставил это разрешение. Если у приложения на самом деле нет правильных разрешений, оно должно сообщить пользователю о проблеме. - Различные типы служб переднего плана были введены с различными версиями платформы Android. Этот код проверяет, на какой версии Android он запущен, и запрашивает соответствующие разрешения.
- Код проверяет наличие исключения
ForegroundServiceStartNotAllowedException
в случае, если он пытается запустить службу переднего плана в ситуации, которая недопустима (например, если он пытается перевести службу на передний план , пока приложение находится в фоновом режиме ).