Запуск службы переднего плана из вашего приложения состоит из двух шагов. Сначала необходимо запустить службу, вызвав метод context.startForegroundService() . Затем служба должна вызвать ServiceCompat.startForeground() чтобы перейти в режим переднего плана.
Предпосылки
В зависимости от того, на какой уровень API ориентировано ваше приложение, существуют некоторые ограничения на то, когда приложение может запускать службу переднего плана.
Приложениям для Android 12 (уровень API 31) и выше запрещено запускать службу переднего плана, пока приложение находится в фоновом режиме, за некоторыми исключениями. Дополнительную информацию и информацию об исключениях из этого правила см. в разделе «Ограничения на запуск службы переднего плана из фонового режима» .
Apps that target Android 14 (API level 34) or higher must request the appropriate permissions for the foreground service type. When the app attempts to promote a service to the foreground, the system checks for the appropriate permissions and throws throws
SecurityExceptionif the app is missing any. For example, if you try to launch a foreground service of typelocation, the system checks to make sure your app already has either theACCESS_COARSE_LOCATIONorACCESS_FINE_LOCATIONpermission. The foreground service type documentation lists the required prerequisites for each foreground service type.
Запустить сервис
Чтобы запустить службу переднего плана, необходимо сначала запустить ее как обычную (не приоритетную) службу:
Котлин
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() .
For example, suppose a fitness app runs a running-tracker service that always needs location information, but might or might not need to play media. You would need to declare both location and mediaPlayback in the manifest. If a user starts a run and just wants their location tracked, your app should call startForeground() and pass just the ACCESS_FINE_LOCATION permission. Then, if the user wants to start playing audio, call startForeground() again and pass the bitwise combination of all the foreground service types (in this case, 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в случае, если он пытается запустить службу переднего плана в ситуации, которая недопустима (например, если он пытается перевести службу на передний план, пока приложение находится в фоновом режиме ).