Я хотел бы запустить службу переднего плана и вызвать LauncherForActivityResult.
Насколько мне известно, я не могу ни запустить службу из ViewModel, ни вызвать LauncherForActivityResult.
Я работаю над приложением для Android, и вначале я просто писал код без реальных архитектурных решений. Но по мере того, как мое приложение росло, я хочу разделить его на отдельные модули. У меня есть BottomBar, где пользователь может ввести некоторую информацию и запустить службу переднего плана, которая просто отслеживает его местоположение. При нажатии кнопки я хочу проверить входные данные в ViewModel и, если они верны, запустить Службу. Но, насколько я знаю, ViewModel не должна знать о контексте Android.
Я хотел бы создать сервис запроса разрешения, который я мог бы использовать с любого экрана, возможно, передавая контекст. Или мой другой вариант заключался в создании функции обратного вызова в viewModel и передаче LocalContext.current, поскольку вы можете получить к ней доступ в Composables.
Мой текущий подход заключается в следующем:
Button(
modifier = Modifier.align(Alignment.CenterHorizontally),
onClick = {
permissionsResultLauncher.launch(
arrayOf(
Manifest.permission.ACCESS_COARSE_LOCATION,
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
Manifest.permission.POST_NOTIFICATIONS
else ""
)
)
// TODO: Only start service if permissions are granted
// TODO: Handle starting service in the ViewModel
Intent(context, PatrolService::class.java).also {
it.action = PatrolService.Actions.START.toString()
context.startService(it)
}
}) {
Text(text = "Járőrözés kezdése")
}
Другая моя проблема заключалась в том, что я могу запросить разрешение, но как я могу проверить, были ли они приняты, поскольку вызов намерения для запуска службы приводит к сбою приложения, если разрешения на уведомления и определение местоположения не принимаются.
Но, насколько я знаю, ViewModel не должна знать о контексте Android.
В частности, существует AndroidViewModel
для предоставления синглтона Application
в качестве Context
. Или вы можете использовать предпочитаемую вами структуру инверсии зависимостей (Dagger/Hilt, Koin и т. д.), чтобы внедрить Application
в вашу модель представления.
Я хотел бы сделать сервис для запроса разрешения
Во-первых, это непрактично. Служба не может запустить пользовательский интерфейс; запрос разрешения включает запуск пользовательского интерфейса.
Во-вторых, смысл обычного сервиса переднего плана заключается в том, чтобы делать что-то, когда у вас нет пользовательского интерфейса на переднем плане и вам нужно делать эти вещи постоянно. Запрос разрешения имеет смысл только в том случае, если у вас есть пользовательский интерфейс на переднем плане, поскольку пользователю необходимо ответить на пользовательский интерфейс для получения разрешения.
Конечно, есть сценарии, когда требуется услуга. Их гораздо меньше, чем могут подумать новички в Android.
который я мог бы использовать с любого экрана
Служба не является заменой стандартных шаблонов повторного использования, таких как наследование и композиция.
Мой текущий подход заключается в следующем
Запуск запроса разрешения из компонуемого объекта — это нормально. Если у вас есть законная потребность в сервисе и вы хотите управлять этим сервисом из модели представления, вы можете это сделать.
поскольку вызов намерения запустить службу приводит к сбою приложения, если разрешения на уведомление и местоположение не принимаются
Ваша служба должна проверить, были ли приняты разрешения, прежде чем выполнять работу, требующую этих разрешений. Если разрешение на уведомление предоставлено, а другие нет, служба может затем поднять Notification
, чтобы вернуть пользователя в ваш пользовательский интерфейс, где пользователь может предоставить эти разрешения.
Ваш сервис или модель представления (или, возможно, ваш составной объект) может проверить, было ли предоставлено конкретное разрешение (используя checkSelfPermission()
в Context
IIRC).