Запуск функций Coroutine на широковещательном приемнике

Я делаю приложение Alarm и использую AlarmManager для установки сигналов тревоги. Я сохраняю каждый будильник с помощью Room после запуска setAlarm в AlarmManager, поэтому я могу позже восстановить их, если телефон выключится и o .

Я запускаю BroadcastReceiver после загрузки устройства, используя руководство с сайта разработчика Android: https://developer.android.com/training/scheduling/alarms#boot

И моя идея состоит в том, чтобы получать будильники из комнаты по методу onReceive Но Room использует приостановку для получения сигналов тревоги, но я не могу запустить ее на onReceive, так как BroadcastReceiver не имеет жизненного цикла.

Как я мог добиться подобного результата?

Я бы сказал, что какой-то одноэлементный объект репозитория должен быть тем, который взаимодействует с Room, а ваш получатель говорит репозиторию что-то делать. Репозиторий может использовать уровень процесса CoroutineScope, который вы специально настроили для такой работы.

CommonsWare 18.10.2022 15:32

@CommonsWare Я думаю, что они что-то берут из комнаты, поэтому им нужен способ, чтобы получатель мог дождаться ввода-вывода.

Tenfour04 18.10.2022 15:54

В точку. В репозитории есть функция приостановки, которая получает информацию. И чтобы вызвать эту функцию, мне нужно запустить ее в области сопрограммы.

MKiperszmid 18.10.2022 17:21
2
3
396
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В этом разделе документации BroadcastReceiver приведен пример того, как это сделать.

Вы можете немного почистить его с помощью функции расширения:

fun BroadcastReceiver.goAsync(
    context: CoroutineContext = EmptyCoroutineContext,
    block: suspend CoroutineScope.() -> Unit
) {
    val pendingResult = goAsync()
    CoroutineScope(SupervisorJob()).launch(context) {
        try {
            block()
        } finally {
            pendingResult.finish()
        }
    }
}

Затем в своем приемнике вы можете использовать его, как показано ниже. Код в блоке goAsync — это сопрограмма. Помните, что вы не должны использовать Dispatchers.Main в этой сопрограмме.

override fun onReceive(context: Context, intent: Intent) = goAsync {
    val repo = MyRepository.getInstance(context)
    val alarms = repo.getAlarms() // a suspend function
    // do stuff
}

Любить это!. Я проверю это сегодня вечером, и если это сработает, отметьте ваш ответ как решение

MKiperszmid 18.10.2022 17:24

Другие вопросы по теме