Make weather updates more reliable
This commit is contained in:
parent
d8e204c5d9
commit
fb3f28d035
@ -19,8 +19,15 @@ import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
|||||||
|
|
||||||
object WeatherHelper {
|
object WeatherHelper {
|
||||||
|
|
||||||
fun updateWeather(context: Context) {
|
fun updateWeather(context: Context, force: Boolean = false) {
|
||||||
WeatherWorker.enqueue(context)
|
if (Preferences.showWeather || force)
|
||||||
|
WeatherWorker.enqueue(context, replace = force)
|
||||||
|
else {
|
||||||
|
removeWeather(context)
|
||||||
|
org.greenrobot.eventbus.EventBus.getDefault().post(
|
||||||
|
com.tommasoberlose.anotherwidget.ui.fragments.MainFragment.UpdateUiMessageEvent()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeWeather(context: Context) {
|
fun removeWeather(context: Context) {
|
||||||
|
@ -17,13 +17,11 @@ import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
|||||||
import com.tommasoberlose.anotherwidget.network.repository.*
|
import com.tommasoberlose.anotherwidget.network.repository.*
|
||||||
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import org.greenrobot.eventbus.EventBus
|
|
||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import kotlin.coroutines.resume
|
||||||
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
|
||||||
class WeatherNetworkApi(val context: Context) {
|
class WeatherNetworkApi(val context: Context) {
|
||||||
suspend fun updateWeather() {
|
suspend fun updateWeather() {
|
||||||
@ -31,7 +29,7 @@ class WeatherNetworkApi(val context: Context) {
|
|||||||
Preferences.weatherProviderError = "-"
|
Preferences.weatherProviderError = "-"
|
||||||
Preferences.weatherProviderLocationError = ""
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
|
||||||
if (Preferences.showWeather && Preferences.customLocationLat != "" && Preferences.customLocationLon != "") {
|
if (Preferences.customLocationLat != "" && Preferences.customLocationLon != "") {
|
||||||
when (Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) {
|
when (Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) {
|
||||||
Constants.WeatherProvider.OPEN_WEATHER -> useOpenWeatherMap(context)
|
Constants.WeatherProvider.OPEN_WEATHER -> useOpenWeatherMap(context)
|
||||||
Constants.WeatherProvider.WEATHER_GOV -> useWeatherGov(context)
|
Constants.WeatherProvider.WEATHER_GOV -> useWeatherGov(context)
|
||||||
@ -42,46 +40,67 @@ class WeatherNetworkApi(val context: Context) {
|
|||||||
Constants.WeatherProvider.YR -> useYrProvider(context)
|
Constants.WeatherProvider.YR -> useYrProvider(context)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!Preferences.showWeather)
|
Preferences.weatherProviderLocationError = context.getString(R.string.weather_provider_error_missing_location)
|
||||||
Preferences.weatherProviderError = context.getString(R.string.show_weather_not_visible)
|
Preferences.weatherProviderError = ""
|
||||||
else {
|
|
||||||
Preferences.weatherProviderLocationError = context.getString(R.string.weather_provider_error_missing_location)
|
|
||||||
Preferences.weatherProviderError = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
WeatherHelper.removeWeather(
|
WeatherHelper.removeWeather(
|
||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
|
||||||
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun useOpenWeatherMap(context: Context) {
|
private suspend fun useOpenWeatherMap(context: Context) {
|
||||||
if (Preferences.weatherProviderApiOpen != "") {
|
if (Preferences.weatherProviderApiOpen != "") {
|
||||||
val helper = OpenWeatherMapHelper(Preferences.weatherProviderApiOpen)
|
val helper = OpenWeatherMapHelper(Preferences.weatherProviderApiOpen)
|
||||||
helper.setUnits(if (Preferences.weatherTempUnit == "F") Units.IMPERIAL else Units.METRIC)
|
helper.setUnits(if (Preferences.weatherTempUnit == "F") Units.IMPERIAL else Units.METRIC)
|
||||||
helper.getCurrentWeatherByGeoCoordinates(Preferences.customLocationLat.toDouble(), Preferences.customLocationLon.toDouble(), object :
|
when (val response = suspendCancellableCoroutine<Any?> { continuation ->
|
||||||
CurrentWeatherCallback {
|
helper.getCurrentWeatherByGeoCoordinates(Preferences.customLocationLat.toDouble(), Preferences.customLocationLon.toDouble(), object :
|
||||||
override fun onSuccess(currentWeather: CurrentWeather?) {
|
CurrentWeatherCallback {
|
||||||
currentWeather?.let {
|
override fun onSuccess(currentWeather: CurrentWeather?) {
|
||||||
Preferences.weatherTemp = currentWeather.main.temp.toFloat()
|
continuation.resume(currentWeather)
|
||||||
Preferences.weatherIcon = currentWeather.weather[0].icon
|
|
||||||
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
|
||||||
MainWidget.updateWidget(context)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onFailure(throwable: Throwable?) {
|
||||||
|
continuation.resume(throwable)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}) {
|
||||||
|
is CurrentWeather -> {
|
||||||
|
Preferences.weatherTemp = response.main.temp.toFloat()
|
||||||
|
Preferences.weatherIcon = response.weather[0].icon
|
||||||
|
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
||||||
|
MainWidget.updateWidget(context)
|
||||||
|
|
||||||
Preferences.weatherProviderError = ""
|
Preferences.weatherProviderError = ""
|
||||||
Preferences.weatherProviderLocationError = ""
|
Preferences.weatherProviderLocationError = ""
|
||||||
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
|
||||||
}
|
}
|
||||||
|
is Throwable -> {
|
||||||
override fun onFailure(throwable: Throwable?) {
|
if (response.javaClass == Throwable::class.java) {
|
||||||
|
// server error, see [OpenWeatherMapHelper.handleCurrentWeatherResponse]
|
||||||
|
if (response.message?.startsWith("UnAuthorized") == true) {
|
||||||
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_invalid_key)
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
}
|
||||||
|
WeatherHelper.removeWeather(
|
||||||
|
context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_connection)
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
||||||
Preferences.weatherProviderLocationError = ""
|
Preferences.weatherProviderLocationError = ""
|
||||||
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
} else {
|
} else {
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key)
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key)
|
||||||
Preferences.weatherProviderLocationError = ""
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
@ -13,11 +13,8 @@ import com.tommasoberlose.anotherwidget.helpers.*
|
|||||||
import com.tommasoberlose.anotherwidget.models.Event
|
import com.tommasoberlose.anotherwidget.models.Event
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
import com.tommasoberlose.anotherwidget.utils.setExactIfCanSchedule
|
import com.tommasoberlose.anotherwidget.utils.setExactIfCanSchedule
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import org.joda.time.Period
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import org.joda.time.Period
|
||||||
|
|
||||||
|
|
||||||
class UpdatesReceiver : BroadcastReceiver() {
|
class UpdatesReceiver : BroadcastReceiver() {
|
||||||
@ -40,10 +37,6 @@ class UpdatesReceiver : BroadcastReceiver() {
|
|||||||
CalendarHelper.updateEventList(context)
|
CalendarHelper.updateEventList(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
"com.sec.android.widgetapp.APPWIDGET_RESIZE",
|
|
||||||
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED,
|
|
||||||
Actions.ACTION_ALARM_UPDATE,
|
|
||||||
Actions.ACTION_UPDATE_GREETINGS,
|
|
||||||
Actions.ACTION_TIME_UPDATE -> {
|
Actions.ACTION_TIME_UPDATE -> {
|
||||||
MainWidget.updateWidget(context)
|
MainWidget.updateWidget(context)
|
||||||
if (intent.hasExtra(EVENT_ID)) {
|
if (intent.hasExtra(EVENT_ID)) {
|
||||||
@ -51,6 +44,13 @@ class UpdatesReceiver : BroadcastReceiver() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"com.sec.android.widgetapp.APPWIDGET_RESIZE",
|
||||||
|
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED,
|
||||||
|
Actions.ACTION_ALARM_UPDATE,
|
||||||
|
Actions.ACTION_UPDATE_GREETINGS -> {
|
||||||
|
MainWidget.updateWidget(context)
|
||||||
|
}
|
||||||
|
|
||||||
Actions.ACTION_CLEAR_NOTIFICATION -> {
|
Actions.ACTION_CLEAR_NOTIFICATION -> {
|
||||||
ActiveNotificationsHelper.clearLastNotification(context)
|
ActiveNotificationsHelper.clearLastNotification(context)
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,12 @@
|
|||||||
package com.tommasoberlose.anotherwidget.receivers
|
package com.tommasoberlose.anotherwidget.receivers
|
||||||
|
|
||||||
import android.app.AlarmManager
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import com.tommasoberlose.anotherwidget.global.Actions
|
import com.tommasoberlose.anotherwidget.global.Actions
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
||||||
import com.tommasoberlose.anotherwidget.services.WeatherWorker
|
import com.tommasoberlose.anotherwidget.services.WeatherWorker
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
|
|
||||||
class WeatherReceiver : BroadcastReceiver() {
|
class WeatherReceiver : BroadcastReceiver() {
|
||||||
|
|
||||||
@ -22,10 +16,9 @@ class WeatherReceiver : BroadcastReceiver() {
|
|||||||
Intent.ACTION_MY_PACKAGE_REPLACED,
|
Intent.ACTION_MY_PACKAGE_REPLACED,
|
||||||
Intent.ACTION_TIMEZONE_CHANGED,
|
Intent.ACTION_TIMEZONE_CHANGED,
|
||||||
Intent.ACTION_LOCALE_CHANGED,
|
Intent.ACTION_LOCALE_CHANGED,
|
||||||
Intent.ACTION_TIME_CHANGED -> setUpdates(context)
|
Intent.ACTION_TIME_CHANGED,
|
||||||
|
|
||||||
Actions.ACTION_WEATHER_UPDATE -> {
|
Actions.ACTION_WEATHER_UPDATE -> {
|
||||||
WeatherWorker.enqueue(context)
|
WeatherHelper.updateWeather(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -33,21 +26,12 @@ class WeatherReceiver : BroadcastReceiver() {
|
|||||||
companion object {
|
companion object {
|
||||||
fun setUpdates(context: Context) {
|
fun setUpdates(context: Context) {
|
||||||
if (Preferences.showWeather) {
|
if (Preferences.showWeather) {
|
||||||
val interval = when (Preferences.weatherRefreshPeriod) {
|
WeatherWorker.enqueueTrigger(context)
|
||||||
0 -> 30
|
|
||||||
1 -> 60
|
|
||||||
2 -> 60L * 3
|
|
||||||
3 -> 60L * 6
|
|
||||||
4 -> 60L * 12
|
|
||||||
5 -> 60L * 24
|
|
||||||
else -> 60
|
|
||||||
}
|
|
||||||
WeatherWorker.enqueuePeriodic(context, interval, TimeUnit.MINUTES)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeUpdates(context: Context) {
|
fun removeUpdates(context: Context) {
|
||||||
WeatherWorker.cancelPeriodic(context)
|
WeatherWorker.cancelTrigger(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,10 @@ import android.content.Context
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.provider.CalendarContract
|
import android.provider.CalendarContract
|
||||||
import androidx.work.Constraints
|
import androidx.work.Constraints
|
||||||
import androidx.work.CoroutineWorker
|
|
||||||
import androidx.work.ExistingWorkPolicy
|
import androidx.work.ExistingWorkPolicy
|
||||||
import androidx.work.OneTimeWorkRequestBuilder
|
import androidx.work.OneTimeWorkRequestBuilder
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
|
import androidx.work.Worker
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
@ -20,140 +20,135 @@ import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
|||||||
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
|
import java.util.*
|
||||||
import me.everything.providers.android.calendar.CalendarProvider
|
import me.everything.providers.android.calendar.CalendarProvider
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import java.util.*
|
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
class UpdateCalendarWorker(private val context: Context, params: WorkerParameters) :
|
class UpdateCalendarWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
|
||||||
CoroutineWorker(context, params) {
|
|
||||||
|
|
||||||
override suspend fun doWork(): Result {
|
override fun doWork(): Result {
|
||||||
withContext(Dispatchers.IO) {
|
val context = applicationContext
|
||||||
UpdatesReceiver.removeUpdates(context)
|
UpdatesReceiver.removeUpdates(context)
|
||||||
val eventRepository = EventRepository(context)
|
val eventRepository = EventRepository(context)
|
||||||
|
|
||||||
if (Preferences.showEvents) {
|
if (Preferences.showEvents) {
|
||||||
if (!context.checkGrantedPermission(Manifest.permission.READ_CALENDAR)) {
|
if (!context.checkGrantedPermission(Manifest.permission.READ_CALENDAR)) {
|
||||||
eventRepository.resetNextEventData()
|
|
||||||
eventRepository.clearEvents()
|
|
||||||
} else {
|
|
||||||
// fetch all events from now to next ACTION_CALENDAR_UPDATE + limit
|
|
||||||
val now = Calendar.getInstance()
|
|
||||||
val limit = Calendar.getInstance().apply {
|
|
||||||
set(Calendar.MILLISECOND, 0)
|
|
||||||
set(Calendar.SECOND, 0)
|
|
||||||
set(Calendar.MINUTE, 0)
|
|
||||||
set(Calendar.HOUR_OF_DAY, 0)
|
|
||||||
add(Calendar.DATE, 1)
|
|
||||||
when (Preferences.showUntil) {
|
|
||||||
0 -> add(Calendar.HOUR, 3)
|
|
||||||
1 -> add(Calendar.HOUR, 6)
|
|
||||||
2 -> add(Calendar.HOUR, 12)
|
|
||||||
3 -> add(Calendar.DAY_OF_MONTH, 1)
|
|
||||||
4 -> add(Calendar.DAY_OF_MONTH, 3)
|
|
||||||
5 -> add(Calendar.DAY_OF_MONTH, 7)
|
|
||||||
6 -> add(Calendar.MINUTE, 30)
|
|
||||||
7 -> add(Calendar.HOUR, 1)
|
|
||||||
else -> add(Calendar.HOUR, 6)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
val eventList = ArrayList<Event>()
|
|
||||||
val provider = CalendarProvider(context)
|
|
||||||
// apply time zone offset to correctly fetch all-day events
|
|
||||||
val data = provider.getInstances(
|
|
||||||
now.timeInMillis + now.timeZone.getOffset(now.timeInMillis).coerceAtMost(0),
|
|
||||||
limit.timeInMillis + limit.timeZone.getOffset(limit.timeInMillis).coerceAtLeast(0)
|
|
||||||
)
|
|
||||||
if (data != null) {
|
|
||||||
val instances = data.list
|
|
||||||
for (instance in instances) {
|
|
||||||
try {
|
|
||||||
val e = provider.getEvent(instance.eventId)
|
|
||||||
if (e == null || e.deleted || CalendarHelper.getFilteredCalendarIdList().contains(e.calendarId))
|
|
||||||
continue
|
|
||||||
if (e.allDay) {
|
|
||||||
val start = Calendar.getInstance()
|
|
||||||
start.timeInMillis = instance.begin
|
|
||||||
val end = Calendar.getInstance()
|
|
||||||
end.timeInMillis = instance.end
|
|
||||||
instance.begin =
|
|
||||||
start.timeInMillis - start.timeZone.getOffset(start.timeInMillis)
|
|
||||||
instance.end =
|
|
||||||
end.timeInMillis - end.timeZone.getOffset(end.timeInMillis)
|
|
||||||
}
|
|
||||||
if (instance.begin <= limit.timeInMillis && now.timeInMillis < instance.end) {
|
|
||||||
/* Following check may result in "fake" all-day events with
|
|
||||||
* non-UTC start/end time, and therefore cannot be found by
|
|
||||||
* Calendar when tapped to open details.
|
|
||||||
// Check all day events
|
|
||||||
val startDate = Calendar.getInstance()
|
|
||||||
startDate.timeInMillis = instance.begin
|
|
||||||
val endDate = Calendar.getInstance()
|
|
||||||
endDate.timeInMillis = instance.end
|
|
||||||
|
|
||||||
val isAllDay = e.allDay || (
|
|
||||||
startDate.get(Calendar.MILLISECOND) == 0
|
|
||||||
&& startDate.get(Calendar.SECOND) == 0
|
|
||||||
&& startDate.get(Calendar.MINUTE) == 0
|
|
||||||
&& startDate.get(Calendar.HOUR_OF_DAY) == 0
|
|
||||||
&& endDate.get(Calendar.MILLISECOND) == 0
|
|
||||||
&& endDate.get(Calendar.SECOND) == 0
|
|
||||||
&& endDate.get(Calendar.MINUTE) == 0
|
|
||||||
&& endDate.get(Calendar.HOUR_OF_DAY) == 0
|
|
||||||
)
|
|
||||||
*/
|
|
||||||
|
|
||||||
eventList.add(
|
|
||||||
Event(
|
|
||||||
id = instance.id,
|
|
||||||
eventID = e.id,
|
|
||||||
title = e.title ?: "",
|
|
||||||
startDate = instance.begin,
|
|
||||||
endDate = instance.end,
|
|
||||||
calendarID = e.calendarId,
|
|
||||||
allDay = e.allDay,
|
|
||||||
address = e.eventLocation ?: "",
|
|
||||||
selfAttendeeStatus = e.selfAttendeeStatus.toInt(),
|
|
||||||
availability = e.availability
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} catch (ignored: Exception) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val sortedEvents = eventList.sortEvents()
|
|
||||||
val filteredEventList = sortedEvents.applyFilters()
|
|
||||||
|
|
||||||
if (filteredEventList.isEmpty()) {
|
|
||||||
eventRepository.resetNextEventData()
|
|
||||||
eventRepository.clearEvents()
|
|
||||||
} else {
|
|
||||||
eventRepository.saveEvents(sortedEvents)
|
|
||||||
//eventRepository.saveNextEventData(filteredEventList.first())
|
|
||||||
}
|
|
||||||
} catch (ignored: java.lang.Exception) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
enqueueTrigger(context)
|
|
||||||
} else {
|
|
||||||
eventRepository.resetNextEventData()
|
eventRepository.resetNextEventData()
|
||||||
eventRepository.clearEvents()
|
eventRepository.clearEvents()
|
||||||
|
} else {
|
||||||
|
// fetch all events from now to next ACTION_CALENDAR_UPDATE + limit
|
||||||
|
val now = Calendar.getInstance()
|
||||||
|
val limit = Calendar.getInstance().apply {
|
||||||
|
set(Calendar.MILLISECOND, 0)
|
||||||
|
set(Calendar.SECOND, 0)
|
||||||
|
set(Calendar.MINUTE, 0)
|
||||||
|
set(Calendar.HOUR_OF_DAY, 0)
|
||||||
|
add(Calendar.DATE, 1)
|
||||||
|
when (Preferences.showUntil) {
|
||||||
|
0 -> add(Calendar.HOUR, 3)
|
||||||
|
1 -> add(Calendar.HOUR, 6)
|
||||||
|
2 -> add(Calendar.HOUR, 12)
|
||||||
|
3 -> add(Calendar.DAY_OF_MONTH, 1)
|
||||||
|
4 -> add(Calendar.DAY_OF_MONTH, 3)
|
||||||
|
5 -> add(Calendar.DAY_OF_MONTH, 7)
|
||||||
|
6 -> add(Calendar.MINUTE, 30)
|
||||||
|
7 -> add(Calendar.HOUR, 1)
|
||||||
|
else -> add(Calendar.HOUR, 6)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
val eventList = ArrayList<Event>()
|
||||||
|
val provider = CalendarProvider(context)
|
||||||
|
// apply time zone offset to correctly fetch all-day events
|
||||||
|
val data = provider.getInstances(
|
||||||
|
now.timeInMillis + now.timeZone.getOffset(now.timeInMillis).coerceAtMost(0),
|
||||||
|
limit.timeInMillis + limit.timeZone.getOffset(limit.timeInMillis).coerceAtLeast(0)
|
||||||
|
)
|
||||||
|
if (data != null) {
|
||||||
|
val instances = data.list
|
||||||
|
for (instance in instances) {
|
||||||
|
try {
|
||||||
|
val e = provider.getEvent(instance.eventId)
|
||||||
|
if (e == null || e.deleted || CalendarHelper.getFilteredCalendarIdList().contains(e.calendarId))
|
||||||
|
continue
|
||||||
|
if (e.allDay) {
|
||||||
|
val start = Calendar.getInstance()
|
||||||
|
start.timeInMillis = instance.begin
|
||||||
|
val end = Calendar.getInstance()
|
||||||
|
end.timeInMillis = instance.end
|
||||||
|
instance.begin =
|
||||||
|
start.timeInMillis - start.timeZone.getOffset(start.timeInMillis)
|
||||||
|
instance.end =
|
||||||
|
end.timeInMillis - end.timeZone.getOffset(end.timeInMillis)
|
||||||
|
}
|
||||||
|
if (instance.begin <= limit.timeInMillis && now.timeInMillis < instance.end) {
|
||||||
|
/* Following check may result in "fake" all-day events with
|
||||||
|
* non-UTC start/end time, and therefore cannot be found by
|
||||||
|
* Calendar when tapped to open details.
|
||||||
|
// Check all day events
|
||||||
|
val startDate = Calendar.getInstance()
|
||||||
|
startDate.timeInMillis = instance.begin
|
||||||
|
val endDate = Calendar.getInstance()
|
||||||
|
endDate.timeInMillis = instance.end
|
||||||
|
|
||||||
|
val isAllDay = e.allDay || (
|
||||||
|
startDate.get(Calendar.MILLISECOND) == 0
|
||||||
|
&& startDate.get(Calendar.SECOND) == 0
|
||||||
|
&& startDate.get(Calendar.MINUTE) == 0
|
||||||
|
&& startDate.get(Calendar.HOUR_OF_DAY) == 0
|
||||||
|
&& endDate.get(Calendar.MILLISECOND) == 0
|
||||||
|
&& endDate.get(Calendar.SECOND) == 0
|
||||||
|
&& endDate.get(Calendar.MINUTE) == 0
|
||||||
|
&& endDate.get(Calendar.HOUR_OF_DAY) == 0
|
||||||
|
)
|
||||||
|
*/
|
||||||
|
|
||||||
|
eventList.add(
|
||||||
|
Event(
|
||||||
|
id = instance.id,
|
||||||
|
eventID = e.id,
|
||||||
|
title = e.title ?: "",
|
||||||
|
startDate = instance.begin,
|
||||||
|
endDate = instance.end,
|
||||||
|
calendarID = e.calendarId,
|
||||||
|
allDay = e.allDay,
|
||||||
|
address = e.eventLocation ?: "",
|
||||||
|
selfAttendeeStatus = e.selfAttendeeStatus.toInt(),
|
||||||
|
availability = e.availability
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val sortedEvents = eventList.sortEvents()
|
||||||
|
val filteredEventList = sortedEvents.applyFilters()
|
||||||
|
|
||||||
|
if (filteredEventList.isEmpty()) {
|
||||||
|
eventRepository.resetNextEventData()
|
||||||
|
eventRepository.clearEvents()
|
||||||
|
} else {
|
||||||
|
eventRepository.saveEvents(sortedEvents)
|
||||||
|
eventRepository.saveNextEventData(filteredEventList.first())
|
||||||
|
}
|
||||||
|
} catch (ignored: java.lang.Exception) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
eventRepository.close()
|
} else {
|
||||||
|
eventRepository.resetNextEventData()
|
||||||
UpdatesReceiver.setUpdates(context)
|
eventRepository.clearEvents()
|
||||||
MainWidget.updateWidget(context)
|
|
||||||
|
|
||||||
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
|
||||||
}
|
}
|
||||||
|
eventRepository.close()
|
||||||
|
UpdatesReceiver.setUpdates(context)
|
||||||
|
|
||||||
|
MainWidget.updateWidget(context)
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
|
||||||
|
if (Preferences.showEvents)
|
||||||
|
enqueueTrigger(context)
|
||||||
return Result.success()
|
return Result.success()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,9 +164,9 @@ class UpdateCalendarWorker(private val context: Context, params: WorkerParameter
|
|||||||
fun enqueueTrigger(context: Context) {
|
fun enqueueTrigger(context: Context) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
WorkManager.getInstance(context).enqueueUniqueWork(
|
WorkManager.getInstance(context).enqueueUniqueWork(
|
||||||
"updateEventListByTrigger",
|
"updateEventListTrigger",
|
||||||
ExistingWorkPolicy.KEEP,
|
ExistingWorkPolicy.KEEP,
|
||||||
OneTimeWorkRequestBuilder<UpdateCalendarWorker>().setConstraints(
|
OneTimeWorkRequestBuilder<Trigger>().setConstraints(
|
||||||
Constraints.Builder().addContentUriTrigger(
|
Constraints.Builder().addContentUriTrigger(
|
||||||
CalendarContract.CONTENT_URI,
|
CalendarContract.CONTENT_URI,
|
||||||
true
|
true
|
||||||
@ -184,9 +179,17 @@ class UpdateCalendarWorker(private val context: Context, params: WorkerParameter
|
|||||||
fun cancelTrigger(context: Context) {
|
fun cancelTrigger(context: Context) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
WorkManager.getInstance(context).cancelUniqueWork(
|
WorkManager.getInstance(context).cancelUniqueWork(
|
||||||
"updateEventListByTrigger"
|
"updateEventListTrigger"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Trigger(context: Context, params: WorkerParameters) : Worker(context, params) {
|
||||||
|
override fun doWork(): Result {
|
||||||
|
if (Preferences.showEvents && !isStopped)
|
||||||
|
enqueue(applicationContext)
|
||||||
|
return Result.success()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,100 +5,104 @@ import android.content.Context
|
|||||||
import android.location.Location
|
import android.location.Location
|
||||||
import android.location.LocationManager
|
import android.location.LocationManager
|
||||||
import androidx.work.CoroutineWorker
|
import androidx.work.CoroutineWorker
|
||||||
import androidx.work.ExistingPeriodicWorkPolicy
|
|
||||||
import androidx.work.ExistingWorkPolicy
|
import androidx.work.ExistingWorkPolicy
|
||||||
import androidx.work.OneTimeWorkRequestBuilder
|
import androidx.work.OneTimeWorkRequestBuilder
|
||||||
import androidx.work.PeriodicWorkRequestBuilder
|
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
|
import androidx.work.Worker
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import com.google.android.gms.common.ConnectionResult
|
import com.google.android.gms.common.ConnectionResult
|
||||||
import com.google.android.gms.common.GoogleApiAvailability
|
import com.google.android.gms.common.GoogleApiAvailability
|
||||||
import com.google.android.gms.location.LocationServices
|
import com.google.android.gms.location.LocationServices
|
||||||
import com.tommasoberlose.anotherwidget.R
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
|
||||||
import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi
|
import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi
|
||||||
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
import org.greenrobot.eventbus.EventBus
|
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class WeatherWorker(private val context: Context, params: WorkerParameters) :
|
class WeatherWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
|
||||||
CoroutineWorker(context, params) {
|
|
||||||
|
|
||||||
override suspend fun doWork(): Result {
|
override suspend fun doWork(): Result {
|
||||||
when {
|
val context = applicationContext
|
||||||
Preferences.customLocationAdd != "" -> {
|
if (Preferences.customLocationAdd == "" &&
|
||||||
withContext(Dispatchers.IO) {
|
context.checkGrantedPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
|
||||||
WeatherNetworkApi(context).updateWeather()
|
) {
|
||||||
}
|
if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
|
||||||
}
|
== ConnectionResult.SUCCESS
|
||||||
context.checkGrantedPermission(Manifest.permission.ACCESS_COARSE_LOCATION) -> {
|
) {
|
||||||
if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
|
suspendCancellableCoroutine { continuation ->
|
||||||
== ConnectionResult.SUCCESS
|
LocationServices.getFusedLocationProviderClient(context).lastLocation.addOnCompleteListener {
|
||||||
) {
|
continuation.resume(if (it.isSuccessful) it.result else null)
|
||||||
suspendCancellableCoroutine { continuation ->
|
|
||||||
LocationServices.getFusedLocationProviderClient(context).lastLocation.addOnCompleteListener {
|
|
||||||
continuation.resume(if (it.isSuccessful) it.result else null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val lm = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
|
||||||
var location: Location? = null
|
|
||||||
for (provider in lm.getProviders(true)) {
|
|
||||||
lm.getLastKnownLocation(provider)?.let {
|
|
||||||
if (location == null ||
|
|
||||||
it.time - location!!.time > 2 * 60 * 1000 ||
|
|
||||||
(it.time - location!!.time > -2 * 60 * 1000 && it.accuracy < location!!.accuracy))
|
|
||||||
location = it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
location
|
|
||||||
}.let { location ->
|
|
||||||
if (location != null) {
|
|
||||||
Preferences.customLocationLat = location.latitude.toString()
|
|
||||||
Preferences.customLocationLon = location.longitude.toString()
|
|
||||||
}
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
WeatherNetworkApi(context).updateWeather()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else -> {
|
val lm = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
||||||
Preferences.weatherProviderLocationError = context.getString(R.string.weather_provider_error_missing_location)
|
var location: Location? = null
|
||||||
Preferences.weatherProviderError = ""
|
for (provider in lm.getProviders(true)) {
|
||||||
WeatherHelper.removeWeather(context)
|
lm.getLastKnownLocation(provider)?.let {
|
||||||
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
if (location == null ||
|
||||||
|
it.time - location!!.time > 2 * 60 * 1000 ||
|
||||||
|
(it.time - location!!.time > -2 * 60 * 1000 && it.accuracy < location!!.accuracy))
|
||||||
|
location = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
location
|
||||||
|
}?.let { location ->
|
||||||
|
Preferences.customLocationLat = location.latitude.toString()
|
||||||
|
Preferences.customLocationLon = location.longitude.toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
WeatherNetworkApi(context).updateWeather()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Preferences.showWeather)
|
||||||
|
enqueueTrigger(context)
|
||||||
return Result.success()
|
return Result.success()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun enqueue(context: Context) {
|
fun enqueue(context: Context, replace: Boolean = false) {
|
||||||
WorkManager.getInstance(context).enqueueUniqueWork(
|
WorkManager.getInstance(context).enqueueUniqueWork(
|
||||||
"updateWeather",
|
"updateWeather",
|
||||||
ExistingWorkPolicy.REPLACE,
|
if (replace) ExistingWorkPolicy.REPLACE else ExistingWorkPolicy.KEEP,
|
||||||
OneTimeWorkRequestBuilder<WeatherWorker>().build()
|
OneTimeWorkRequestBuilder<WeatherWorker>().build()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun enqueuePeriodic(context: Context, interval: Long, unit: TimeUnit) {
|
fun enqueueTrigger(context: Context) {
|
||||||
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
|
val interval = when (Preferences.weatherRefreshPeriod) {
|
||||||
"updateWeatherPeriodically",
|
0 -> 30
|
||||||
ExistingPeriodicWorkPolicy.REPLACE,
|
1 -> 60
|
||||||
PeriodicWorkRequestBuilder<WeatherWorker>(interval, unit).build()
|
2 -> 60L * 3
|
||||||
|
3 -> 60L * 6
|
||||||
|
4 -> 60L * 12
|
||||||
|
5 -> 60L * 24
|
||||||
|
else -> 60
|
||||||
|
}
|
||||||
|
WorkManager.getInstance(context).enqueueUniqueWork(
|
||||||
|
"updateWeatherTrigger",
|
||||||
|
ExistingWorkPolicy.REPLACE,
|
||||||
|
OneTimeWorkRequestBuilder<Trigger>().setInitialDelay(
|
||||||
|
interval, TimeUnit.MINUTES
|
||||||
|
).build()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun cancelPeriodic(context: Context) {
|
fun cancelTrigger(context: Context) {
|
||||||
WorkManager.getInstance(context).cancelUniqueWork(
|
WorkManager.getInstance(context).cancelUniqueWork(
|
||||||
"updateWeatherPeriodically"
|
"updateWeatherTrigger"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Trigger(context: Context, params: WorkerParameters) : Worker(context, params) {
|
||||||
|
override fun doWork(): Result {
|
||||||
|
if (Preferences.showWeather && !isStopped)
|
||||||
|
enqueue(applicationContext)
|
||||||
|
return Result.success()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ class WeatherProviderActivity : AppCompatActivity() {
|
|||||||
updateListItem()
|
updateListItem()
|
||||||
binding.loader.isVisible = true
|
binding.loader.isVisible = true
|
||||||
|
|
||||||
WeatherHelper.updateWeather(this@WeatherProviderActivity)
|
WeatherHelper.updateWeather(this@WeatherProviderActivity, true)
|
||||||
}
|
}
|
||||||
.clicked(R.id.radioButton) {
|
.clicked(R.id.radioButton) {
|
||||||
if (Preferences.weatherProvider != provider.rawValue) {
|
if (Preferences.weatherProvider != provider.rawValue) {
|
||||||
@ -70,7 +70,7 @@ class WeatherProviderActivity : AppCompatActivity() {
|
|||||||
updateListItem()
|
updateListItem()
|
||||||
binding.loader.isVisible = true
|
binding.loader.isVisible = true
|
||||||
|
|
||||||
WeatherHelper.updateWeather(this@WeatherProviderActivity)
|
WeatherHelper.updateWeather(this@WeatherProviderActivity, true)
|
||||||
}
|
}
|
||||||
.checked(R.id.radioButton, provider.rawValue == Preferences.weatherProvider)
|
.checked(R.id.radioButton, provider.rawValue == Preferences.weatherProvider)
|
||||||
.with<TextView>(R.id.text2) {
|
.with<TextView>(R.id.text2) {
|
||||||
@ -89,7 +89,7 @@ class WeatherProviderActivity : AppCompatActivity() {
|
|||||||
.clicked(R.id.action_configure) {
|
.clicked(R.id.action_configure) {
|
||||||
BottomSheetWeatherProviderSettings(this) {
|
BottomSheetWeatherProviderSettings(this) {
|
||||||
binding.loader.isVisible = true
|
binding.loader.isVisible = true
|
||||||
WeatherHelper.updateWeather(this@WeatherProviderActivity)
|
WeatherHelper.updateWeather(this@WeatherProviderActivity, true)
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
.visibility(R.id.action_configure, if (/*WeatherHelper.isKeyRequired(provider) && */provider.rawValue == Preferences.weatherProvider) View.VISIBLE else View.GONE)
|
.visibility(R.id.action_configure, if (/*WeatherHelper.isKeyRequired(provider) && */provider.rawValue == Preferences.weatherProvider) View.VISIBLE else View.GONE)
|
||||||
|
@ -23,6 +23,7 @@ import com.tommasoberlose.anotherwidget.components.MaterialBottomSheetDialog
|
|||||||
import com.tommasoberlose.anotherwidget.databinding.FragmentPreferencesBinding
|
import com.tommasoberlose.anotherwidget.databinding.FragmentPreferencesBinding
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
||||||
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
||||||
import com.tommasoberlose.anotherwidget.receivers.WeatherReceiver
|
import com.tommasoberlose.anotherwidget.receivers.WeatherReceiver
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||||
@ -137,7 +138,7 @@ class PreferencesFragment : Fragment() {
|
|||||||
if (enabled) {
|
if (enabled) {
|
||||||
Preferences.weatherProviderError = ""
|
Preferences.weatherProviderError = ""
|
||||||
Preferences.weatherProviderLocationError = ""
|
Preferences.weatherProviderLocationError = ""
|
||||||
WeatherReceiver.setUpdates(requireContext())
|
WeatherHelper.updateWeather(requireContext())
|
||||||
} else {
|
} else {
|
||||||
WeatherReceiver.removeUpdates(requireContext())
|
WeatherReceiver.removeUpdates(requireContext())
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,6 @@ class MainViewModel(context: Application) : AndroidViewModel(context) {
|
|||||||
|
|
||||||
addSource(Preferences.asLiveData(Preferences::showWeather)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::showWeather)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::weatherProvider)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::weatherProvider)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::weatherTempUnit)) { value = true }
|
|
||||||
addSource(Preferences.asLiveData(Preferences::weatherIconPack)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::weatherIconPack)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::customLocationLat)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::customLocationLat)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::customLocationLon)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::customLocationLon)) { value = true }
|
||||||
|
@ -32,7 +32,7 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
|
|
||||||
override fun onEnabled(context: Context) {
|
override fun onEnabled(context: Context) {
|
||||||
CalendarHelper.updateEventList(context)
|
CalendarHelper.updateEventList(context)
|
||||||
WeatherReceiver.setUpdates(context)
|
WeatherHelper.updateWeather(context)
|
||||||
MediaPlayerHelper.updatePlayingMediaInfo(context)
|
MediaPlayerHelper.updatePlayingMediaInfo(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user