Создание службы запуска AlarmManager для обновления БД

#android #kotlin #service #retrofit2 #alarmmanager

#Android #kotlin #Обслуживание #retrofit2 #alarmmanager

Вопрос:

Итак, я пытаюсь запустить службу, которая отправляет определенные данные о комнате на сервер каждую полночь (примерно) и удаляет их из локальной базы данных. Читая документы Android, я пришел к выводу, что лучшим подходом в настоящее время является настройка будильника, который срабатывает в полночь и запускает службу, которая выполняет синхронизацию). Хотя я не совсем уверен, какой тип сервиса мне следует использовать, мои файлы выглядят так:

MainActivity.kt

     alarmMgr = applicationContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager?

    alarmIntent = Intent(this, SendTakesReceiver::class.java).let { intent ->
        PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
    }


    // Set the alarm to send takes at approximately 00:00 a.m.
    val calendar: Calendar = Calendar.getInstance().apply {
        timeInMillis = System.currentTimeMillis()
        set(Calendar.HOUR_OF_DAY, 0)
    }


    // With setInexactRepeating(), you have to use one of the AlarmManager interval
    // constants--in this case, AlarmManager.INTERVAL_DAY.
    alarmMgr?.setInexactRepeating(
        AlarmManager.RTC_WAKEUP,
        calendar.timeInMillis,
        AlarmManager.INTERVAL_DAY,
        alarmIntent
    )
  

SendtakesReceiver.kt

 class SendTakesReceiver : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            //these following logs are always shown
            Log.d("TAKES INTENT", intent.toString())

            if (intent != null) {
                context?.run {
                    Log.d("TAKES SERVICE", intent.toString())
                    startService(intent)
                }
            }

        }
}
  

SendTakesService.kt

 class SendTakesService : Service() {
        val sp: SharedPreferences = getSharedPreferences("login", Context.MODE_PRIVATE)

        private var prescriptionTakeDao =
                      AppDatabase.getDatabase(applicationContext).prescriptionTakeDao()


        override fun onCreate() {
            super.onCreate()
            Log.d("TakesService", "onCreate()")
        }

        override fun onBind(intent: Intent?): IBinder? {
            return null
        }
}
  

И, наконец, в моем файле манифеста у меня есть (внутри тега приложения):

 <receiver
    android:name=".src.ui.prescriptions.SendTakesReceiver"
    android:enabled="true" />

<service
    android:name="com.glik.glik.src.services.SendTakesService"
    android:enabled="true"
    android:process=":SendTakes">
</service>
  

Но проблема в том, что ни один из классов служб (Service, IntentService, JobIntentService), которые я пытался использовать, не вызывает их основной метод. Например, здесь onCreate() журнал никогда не отображается. Я видел бесчисленное множество подобных вопросов, касающихся того, что службы не запускаются, но, похоже, я не могу точно определить точную ошибку, которую я здесь делаю, из-за которой служба не запускается. Если бы кто-нибудь мог помочь мне найти его или, возможно, порекомендовать более элегантный подход к синхронизации БД, я был бы очень благодарен. Заранее спасибо.

Комментарии:

1. Служба не будет работать в Android 8 и выше, вам необходимо использовать службу переднего плана.

2. Это правда. Я изменил свой приемник, чтобы проверить, должен ли он запускать foregroundservice или нет, но onCreate метод по-прежнему не вызывается

3. Для запуска службы переднего плана необходимо отправить уведомление. developer.android.com/guide/components/foreground-services

Ответ №1:

В зависимости от производителя используемого телефона при таком подходе вы столкнетесь с различными проблемами. Смотрите https://dontkillmyapp.com /

Вы должны использовать WorkManager, чтобы уменьшить использование батареи и избежать необходимости вручную обрабатывать множество угловых случаев: https://developer.android.com/topic/libraries/architecture/workmanager/basics