From 388653f62baf2d39f556e8753caa9597e83dd94a Mon Sep 17 00:00:00 2001 From: azuo Date: Sun, 3 Oct 2021 16:34:56 +0800 Subject: [PATCH] Meet some mandatory requirements for migrating to Android 12 1. Replace foreground services with Workers 2. Support approximate location 3. Fallback to inexact alarms if the SCHEDULE_EXACT_ALARM permission is revoked 4. Specify the mutability of each PendingIntent 5. Explicitly declare the android:exported attribute for app components that use intent filters --- app/src/main/AndroidManifest.xml | 21 +-- .../anotherwidget/helpers/AlarmHelper.kt | 7 +- .../anotherwidget/helpers/CalendarHelper.kt | 4 +- .../anotherwidget/helpers/GreetingsHelper.kt | 10 +- .../anotherwidget/helpers/IntentHelper.kt | 2 +- .../anotherwidget/helpers/WeatherHelper.kt | 18 +- .../receivers/ActivityDetectionReceiver.kt | 13 +- .../receivers/NotificationListener.kt | 7 +- .../receivers/UpdatesReceiver.kt | 21 ++- .../receivers/WeatherReceiver.kt | 46 ++--- .../anotherwidget/services/LocationService.kt | 144 ---------------- ...ndarService.kt => UpdateCalendarWorker.kt} | 160 ++++++------------ .../anotherwidget/services/WeatherWorker.kt | 107 ++++++++++++ .../ui/activities/tabs/CustomDateActivity.kt | 1 + .../tabs/WeatherProviderActivity.kt | 14 +- .../ui/fragments/SettingsFragment.kt | 16 +- .../ui/fragments/tabs/WeatherFragment.kt | 19 +-- .../anotherwidget/ui/widgets/AlignedWidget.kt | 30 ++-- .../anotherwidget/ui/widgets/ClockWidget.kt | 2 +- .../ui/widgets/StandardWidget.kt | 32 ++-- .../anotherwidget/utils/Extensions.kt | 8 + 21 files changed, 267 insertions(+), 415 deletions(-) delete mode 100644 app/src/main/java/com/tommasoberlose/anotherwidget/services/LocationService.kt rename app/src/main/java/com/tommasoberlose/anotherwidget/services/{UpdateCalendarService.kt => UpdateCalendarWorker.kt} (57%) create mode 100644 app/src/main/java/com/tommasoberlose/anotherwidget/services/WeatherWorker.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 75a0ce5..292c24b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,14 +6,15 @@ + - + - + @@ -44,11 +45,10 @@ - + - @@ -112,7 +112,7 @@ - @@ -140,17 +140,6 @@ - - - diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/AlarmHelper.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/AlarmHelper.kt index 595dc39..94a9c53 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/AlarmHelper.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/AlarmHelper.kt @@ -9,6 +9,7 @@ import android.util.Log import com.tommasoberlose.anotherwidget.global.Actions import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver +import com.tommasoberlose.anotherwidget.utils.setExactIfCanSchedule import java.text.SimpleDateFormat import java.util.* @@ -44,14 +45,14 @@ object AlarmHelper { val intent = Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_ALARM_UPDATE } - setExact( + setExactIfCanSchedule( AlarmManager.RTC, trigger, PendingIntent.getBroadcast( context, ALARM_UPDATE_ID, intent, - 0 + PendingIntent.FLAG_IMMUTABLE ) ) } @@ -62,7 +63,7 @@ object AlarmHelper { val intent = Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_ALARM_UPDATE } - cancel(PendingIntent.getBroadcast(context, ALARM_UPDATE_ID, intent, 0)) + cancel(PendingIntent.getBroadcast(context, ALARM_UPDATE_ID, intent, PendingIntent.FLAG_IMMUTABLE)) } } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/CalendarHelper.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/CalendarHelper.kt index de10b4e..01bf676 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/CalendarHelper.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/CalendarHelper.kt @@ -7,7 +7,7 @@ import android.provider.CalendarContract import com.tommasoberlose.anotherwidget.services.EventListenerJob import com.tommasoberlose.anotherwidget.models.Event import com.tommasoberlose.anotherwidget.global.Preferences -import com.tommasoberlose.anotherwidget.services.UpdateCalendarService +import com.tommasoberlose.anotherwidget.services.UpdateCalendarWorker import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission import me.everything.providers.android.calendar.CalendarProvider import java.util.* @@ -19,7 +19,7 @@ import kotlin.collections.ArrayList object CalendarHelper { fun updateEventList(context: Context) { - UpdateCalendarService.enqueueWork(context) + UpdateCalendarWorker.enqueue(context) } fun getCalendarList(context: Context): List { diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/GreetingsHelper.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/GreetingsHelper.kt index 04432d3..c033250 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/GreetingsHelper.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/GreetingsHelper.kt @@ -37,7 +37,7 @@ object GreetingsHelper { Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_UPDATE_GREETINGS }, - 0) + PendingIntent.FLAG_IMMUTABLE) ) setRepeating( @@ -51,7 +51,7 @@ object GreetingsHelper { Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_UPDATE_GREETINGS }, - 0) + PendingIntent.FLAG_IMMUTABLE) ) setRepeating( @@ -65,7 +65,7 @@ object GreetingsHelper { Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_UPDATE_GREETINGS }, - 0) + PendingIntent.FLAG_IMMUTABLE) ) setRepeating( @@ -79,14 +79,14 @@ object GreetingsHelper { Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_UPDATE_GREETINGS }, - 0) + PendingIntent.FLAG_IMMUTABLE) ) } else { listOf(MORNING_TIME, MORNING_TIME_END, EVENING_TIME, NIGHT_TIME).forEach { cancel(PendingIntent.getBroadcast(context, it, Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_UPDATE_GREETINGS - }, 0)) + }, PendingIntent.FLAG_IMMUTABLE)) } } } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/IntentHelper.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/IntentHelper.kt index a0f2b61..26c48aa 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/IntentHelper.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/IntentHelper.kt @@ -32,7 +32,7 @@ object IntentHelper { return if (intent.flags and Intent.FLAG_ACTIVITY_NEW_TASK == Intent.FLAG_ACTIVITY_NEW_TASK) PendingIntent.getActivity(context, requestCode, intent, flags) else - PendingIntent.getBroadcast(context, requestCode, intent, 0) + PendingIntent.getBroadcast(context, requestCode, intent, flags) } fun getWidgetUpdateIntent(context: Context): Intent { diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/WeatherHelper.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/WeatherHelper.kt index 177401f..cf2152e 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/WeatherHelper.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/WeatherHelper.kt @@ -7,7 +7,7 @@ import com.tommasoberlose.anotherwidget.R import com.tommasoberlose.anotherwidget.global.Constants import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi -import com.tommasoberlose.anotherwidget.services.LocationService +import com.tommasoberlose.anotherwidget.services.WeatherWorker import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission import com.tommasoberlose.anotherwidget.utils.isDarkTheme @@ -19,20 +19,8 @@ import com.tommasoberlose.anotherwidget.utils.isDarkTheme object WeatherHelper { - suspend fun updateWeather(context: Context) { - Kotpref.init(context) - if (Preferences.customLocationAdd != "") { - WeatherNetworkApi(context).updateWeather() - } else if (context.checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION)) { - LocationService.requestNewLocation(context) - } else { - Preferences.weatherProviderLocationError = context.getString(R.string.weather_provider_error_missing_location) - Preferences.weatherProviderError = "" - removeWeather(context) - org.greenrobot.eventbus.EventBus.getDefault().post( - com.tommasoberlose.anotherwidget.ui.fragments.MainFragment.UpdateUiMessageEvent() - ) - } + fun updateWeather(context: Context) { + WeatherWorker.enqueue(context) } fun removeWeather(context: Context) { diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/ActivityDetectionReceiver.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/ActivityDetectionReceiver.kt index bf4fd94..23fc02c 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/ActivityDetectionReceiver.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/ActivityDetectionReceiver.kt @@ -21,6 +21,7 @@ import com.google.android.gms.location.* import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission +import com.tommasoberlose.anotherwidget.utils.setExactIfCanSchedule import java.util.* import java.util.concurrent.TimeUnit @@ -79,7 +80,7 @@ class ActivityDetectionReceiver : BroadcastReceiver() { context, 2, Intent(context, ActivityDetectionReceiver::class.java), - 0 + PendingIntent.FLAG_IMMUTABLE ) ) @@ -98,7 +99,7 @@ class ActivityDetectionReceiver : BroadcastReceiver() { context, 2, Intent(context, ActivityDetectionReceiver::class.java), - 0 + PendingIntent.FLAG_IMMUTABLE ) ) @@ -108,7 +109,7 @@ class ActivityDetectionReceiver : BroadcastReceiver() { context, 2, Intent(context, ActivityDetectionReceiver::class.java), - 0 + PendingIntent.FLAG_IMMUTABLE ).cancel() } } @@ -167,14 +168,14 @@ class ActivityDetectionReceiver : BroadcastReceiver() { private fun setTimeout(context: Context) { with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) { - setExact( + setExactIfCanSchedule( AlarmManager.RTC, Calendar.getInstance().timeInMillis + 5 * 60 * 1000, PendingIntent.getBroadcast( context, 5, Intent(context, ActivityDetectionReceiver::class.java), - 0 + PendingIntent.FLAG_IMMUTABLE ) ) } @@ -187,7 +188,7 @@ class ActivityDetectionReceiver : BroadcastReceiver() { context, 5, Intent(context, ActivityDetectionReceiver::class.java), - 0 + PendingIntent.FLAG_IMMUTABLE ) ) } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/NotificationListener.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/NotificationListener.kt index 56bb92e..87cf74f 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/NotificationListener.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/NotificationListener.kt @@ -16,6 +16,7 @@ import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget +import com.tommasoberlose.anotherwidget.utils.setExactIfCanSchedule import java.lang.Exception import java.util.* @@ -83,7 +84,7 @@ class NotificationListener : NotificationListenerService() { } val timeoutPref = Constants.GlanceNotificationTimer.fromInt(Preferences.hideNotificationAfter) if (timeoutPref != Constants.GlanceNotificationTimer.WHEN_DISMISSED) { - setExact( + setExactIfCanSchedule( AlarmManager.RTC, Calendar.getInstance().timeInMillis + when (timeoutPref) { Constants.GlanceNotificationTimer.HALF_MINUTE -> 30 * 1000 @@ -97,7 +98,7 @@ class NotificationListener : NotificationListenerService() { context, 5, intent, - 0 + PendingIntent.FLAG_IMMUTABLE ) ) } @@ -110,7 +111,7 @@ class NotificationListener : NotificationListenerService() { val intent = Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_CLEAR_NOTIFICATION } - cancel(PendingIntent.getBroadcast(context, 5, intent, 0)) + cancel(PendingIntent.getBroadcast(context, 5, intent, PendingIntent.FLAG_IMMUTABLE)) } } } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt index 11ca792..c599294 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt @@ -12,6 +12,7 @@ import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.helpers.* import com.tommasoberlose.anotherwidget.models.Event import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget +import com.tommasoberlose.anotherwidget.utils.setExactIfCanSchedule import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch @@ -55,11 +56,9 @@ class UpdatesReceiver : BroadcastReceiver() { } Actions.ACTION_REFRESH -> { - GlobalScope.launch(Dispatchers.IO) { - CalendarHelper.updateEventList(context) - MediaPlayerHelper.updatePlayingMediaInfo(context) - WeatherHelper.updateWeather(context) - } + CalendarHelper.updateEventList(context) + MediaPlayerHelper.updatePlayingMediaInfo(context) + WeatherHelper.updateWeather(context) } } } @@ -74,7 +73,7 @@ class UpdatesReceiver : BroadcastReceiver() { if (eventId == null) { // schedule ACTION_CALENDAR_UPDATE at midnight (ACTION_DATE_CHANGED no longer works) with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) { - setExact( + setExactIfCanSchedule( AlarmManager.RTC, Calendar.getInstance().apply { set(Calendar.MILLISECOND, 0) @@ -89,7 +88,7 @@ class UpdatesReceiver : BroadcastReceiver() { Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_CALENDAR_UPDATE }, - 0 + PendingIntent.FLAG_IMMUTABLE ) ) } @@ -164,7 +163,7 @@ class UpdatesReceiver : BroadcastReceiver() { add(Calendar.DATE, 1) }.timeInMillis <= fireTime) return with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) { - setExact( + setExactIfCanSchedule( AlarmManager.RTC, fireTime.coerceAtLeast(now.timeInMillis + 1000 * 60), PendingIntent.getBroadcast( @@ -175,7 +174,7 @@ class UpdatesReceiver : BroadcastReceiver() { if (event.startDate > now.timeInMillis) putExtra(EVENT_ID, event.id) }, - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) ) } @@ -185,12 +184,12 @@ class UpdatesReceiver : BroadcastReceiver() { with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) { cancel(PendingIntent.getBroadcast(context, 0, Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_CALENDAR_UPDATE - }, 0)) + }, PendingIntent.FLAG_IMMUTABLE)) val eventRepository = EventRepository(context) eventRepository.getFutureEvents().forEach { cancel(PendingIntent.getBroadcast(context, it.id.toInt(), Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_TIME_UPDATE - }, 0)) + }, PendingIntent.FLAG_IMMUTABLE)) } eventRepository.close() } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/WeatherReceiver.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/WeatherReceiver.kt index f352b28..0092180 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/WeatherReceiver.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/WeatherReceiver.kt @@ -7,11 +7,11 @@ import android.content.Context import android.content.Intent import com.tommasoberlose.anotherwidget.global.Actions import com.tommasoberlose.anotherwidget.global.Preferences -import com.tommasoberlose.anotherwidget.helpers.WeatherHelper +import com.tommasoberlose.anotherwidget.services.WeatherWorker import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch -import java.util.* +import java.util.concurrent.TimeUnit class WeatherReceiver : BroadcastReceiver() { @@ -22,16 +22,18 @@ class WeatherReceiver : BroadcastReceiver() { Intent.ACTION_MY_PACKAGE_REPLACED, Intent.ACTION_TIMEZONE_CHANGED, Intent.ACTION_LOCALE_CHANGED, - Intent.ACTION_TIME_CHANGED, - Actions.ACTION_WEATHER_UPDATE -> setUpdates(context) + Intent.ACTION_TIME_CHANGED -> setUpdates(context) + + Actions.ACTION_WEATHER_UPDATE -> { + WeatherWorker.enqueue(context) + } } } companion object { - private const val MINUTE = 60 * 1000L fun setUpdates(context: Context) { if (Preferences.showWeather) { - val interval = MINUTE * when (Preferences.weatherRefreshPeriod) { + val interval = when (Preferences.weatherRefreshPeriod) { 0 -> 30 1 -> 60 2 -> 60L * 3 @@ -40,40 +42,12 @@ class WeatherReceiver : BroadcastReceiver() { 5 -> 60L * 24 else -> 60 } - with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) { - setExact( - AlarmManager.RTC, - System.currentTimeMillis() + interval, - PendingIntent.getBroadcast(context, 0, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0) - ) - } - GlobalScope.launch(Dispatchers.IO) { - WeatherHelper.updateWeather(context) - } - } - } - - fun setOneTimeUpdate(context: Context) { - if (Preferences.showWeather) { - listOf(10, 20, 30).forEach { - with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) { - setExactAndAllowWhileIdle( - AlarmManager.RTC, - it * MINUTE, - PendingIntent.getBroadcast(context, it, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0) - ) - } - } + WeatherWorker.enqueue(context, interval, TimeUnit.MINUTES) } } fun removeUpdates(context: Context) { - with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) { - cancel(PendingIntent.getBroadcast(context, 0, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0)) - listOf(10, 20, 30).forEach { - cancel(PendingIntent.getBroadcast(context, it, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0)) - } - } + WeatherWorker.cancel(context) } } } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/services/LocationService.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/services/LocationService.kt deleted file mode 100644 index 73bb497..0000000 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/services/LocationService.kt +++ /dev/null @@ -1,144 +0,0 @@ -package com.tommasoberlose.anotherwidget.services - -import android.Manifest -import android.app.* -import android.app.job.JobScheduler -import android.content.Context -import android.content.Intent -import android.content.pm.PackageManager -import android.location.Address -import android.location.Geocoder -import android.os.IBinder -import android.util.Log -import androidx.core.app.* -import androidx.core.content.ContextCompat -import com.google.android.gms.location.LocationServices -import com.tommasoberlose.anotherwidget.R -import com.tommasoberlose.anotherwidget.global.Preferences -import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi -import com.tommasoberlose.anotherwidget.ui.activities.MainActivity -import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment -import kotlinx.coroutines.* -import org.greenrobot.eventbus.EventBus -import java.lang.Exception -import java.util.* -import kotlin.collections.ArrayList - -class LocationService : Service() { - - private var job: Job? = null - - override fun onCreate() { - super.onCreate() - startForeground(LOCATION_ACCESS_NOTIFICATION_ID, getLocationAccessNotification()) - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - startForeground(LOCATION_ACCESS_NOTIFICATION_ID, getLocationAccessNotification()) - job?.cancel() - job = GlobalScope.launch(Dispatchers.IO) { - if (ActivityCompat.checkSelfPermission( - this@LocationService, - Manifest.permission.ACCESS_FINE_LOCATION - ) == PackageManager.PERMISSION_GRANTED - ) { - if (com.google.android.gms.common.GoogleApiAvailability.getInstance() - .isGooglePlayServicesAvailable(this@LocationService) - == com.google.android.gms.common.ConnectionResult.SUCCESS - ) { - LocationServices.getFusedLocationProviderClient(this@LocationService).lastLocation - } else { - val lm = getSystemService(LOCATION_SERVICE) as android.location.LocationManager - var location: android.location.Location? = null - for (provider in arrayOf( - "fused", // LocationManager.FUSED_PROVIDER, - android.location.LocationManager.GPS_PROVIDER, - android.location.LocationManager.NETWORK_PROVIDER, - android.location.LocationManager.PASSIVE_PROVIDER - )) { - if (lm.isProviderEnabled(provider)) { - location = lm.getLastKnownLocation(provider) - if (location != null) break - } - } - com.google.android.gms.tasks.Tasks.forResult(location) - }.addOnCompleteListener { task -> - val networkApi = WeatherNetworkApi(this@LocationService) - if (task.isSuccessful) { - val location = task.result - if (location != null) { - Preferences.customLocationLat = location.latitude.toString() - Preferences.customLocationLon = location.longitude.toString() - } - - CoroutineScope(Dispatchers.IO).launch { - networkApi.updateWeather() - withContext(Dispatchers.Main) { - stopSelf() - } - } - EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent()) - } else { - CoroutineScope(Dispatchers.IO).launch { - networkApi.updateWeather() - withContext(Dispatchers.Main) { - stopSelf() - } - } - EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent()) - } - } - } else { - stopSelf() - } - } - return START_STICKY - } - - override fun onDestroy() { - super.onDestroy() - job?.cancel() - job = null - } - - companion object { - const val LOCATION_ACCESS_NOTIFICATION_ID = 28465 - - @JvmStatic - fun requestNewLocation(context: Context) { - ContextCompat.startForegroundService(context, Intent(context, LocationService::class.java)) - } - } - - override fun onBind(intent: Intent?): IBinder? { - return null - } - - private fun getLocationAccessNotification(): Notification { - with(NotificationManagerCompat.from(this)) { - // Create channel - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { - createNotificationChannel( - NotificationChannel( - getString(R.string.location_access_notification_channel_id), - getString(R.string.location_access_notification_channel_name), - NotificationManager.IMPORTANCE_LOW - ).apply { - description = getString(R.string.location_access_notification_channel_description) - } - ) - } - - val builder = NotificationCompat.Builder(this@LocationService, getString(R.string.location_access_notification_channel_id)) - .setSmallIcon(R.drawable.ic_stat_notification) - .setContentTitle(getString(R.string.location_access_notification_title)) - .setOngoing(true) - .setColor(ContextCompat.getColor(this@LocationService, R.color.colorAccent)) - - // Main intent that open the activity - builder.setContentIntent(PendingIntent.getActivity(this@LocationService, 0, Intent(this@LocationService, MainActivity::class.java), PendingIntent.FLAG_UPDATE_CURRENT)) - - return builder.build() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdateCalendarService.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdateCalendarWorker.kt similarity index 57% rename from app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdateCalendarService.kt rename to app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdateCalendarWorker.kt index be45806..6f610a9 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdateCalendarService.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdateCalendarWorker.kt @@ -1,15 +1,12 @@ package com.tommasoberlose.anotherwidget.services import android.Manifest -import android.app.* import android.content.Context -import android.content.Intent -import android.os.IBinder -import android.util.Log -import androidx.core.app.NotificationCompat -import androidx.core.app.NotificationManagerCompat -import androidx.core.content.ContextCompat -import com.tommasoberlose.anotherwidget.R +import androidx.work.CoroutineWorker +import androidx.work.ExistingWorkPolicy +import androidx.work.OneTimeWorkRequestBuilder +import androidx.work.WorkManager +import androidx.work.WorkerParameters import com.tommasoberlose.anotherwidget.db.EventRepository import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.helpers.CalendarHelper @@ -17,81 +14,54 @@ import com.tommasoberlose.anotherwidget.helpers.CalendarHelper.applyFilters import com.tommasoberlose.anotherwidget.helpers.CalendarHelper.sortEvents import com.tommasoberlose.anotherwidget.models.Event import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver -import com.tommasoberlose.anotherwidget.ui.activities.MainActivity import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import me.everything.providers.android.calendar.CalendarProvider import org.greenrobot.eventbus.EventBus import java.util.* import kotlin.collections.ArrayList -class UpdateCalendarService : Service() { +class UpdateCalendarWorker(private val context: Context, params: WorkerParameters) : + CoroutineWorker(context, params) { - companion object { - const val CALENDAR_SYNC_NOTIFICATION_ID = 28468 - fun enqueueWork(context: Context) { - ContextCompat.startForegroundService(context, Intent(context, UpdateCalendarService::class.java)) - } - } + override suspend fun doWork(): Result { + withContext(Dispatchers.IO) { + UpdatesReceiver.removeUpdates(context) + val eventRepository = EventRepository(context) - override fun onCreate() { - super.onCreate() - startForeground(CALENDAR_SYNC_NOTIFICATION_ID, getCalendarSyncNotification()) - } - - private var job: Job? = null - - override fun onBind(intent: Intent?): IBinder? { - return null - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - startForeground(CALENDAR_SYNC_NOTIFICATION_ID, getCalendarSyncNotification()) - job?.cancel() - job = GlobalScope.launch(Dispatchers.IO) { - - UpdatesReceiver.removeUpdates(this@UpdateCalendarService) - - val eventRepository = EventRepository(this@UpdateCalendarService) if (Preferences.showEvents) { - val eventList = ArrayList() - - // 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) - } - } - - if (!checkGrantedPermission( - Manifest.permission.READ_CALENDAR - ) - ) { + if (!context.checkGrantedPermission(Manifest.permission.READ_CALENDAR)) { eventRepository.resetNextEventData() eventRepository.clearEvents() Preferences.showEvents = false } 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 provider = CalendarProvider(this@UpdateCalendarService) + val eventList = ArrayList() + 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), @@ -157,20 +127,16 @@ class UpdateCalendarService : Service() { } val sortedEvents = eventList.sortEvents() - val filteredEventList = sortedEvents - .applyFilters() + val filteredEventList = sortedEvents.applyFilters() if (filteredEventList.isEmpty()) { eventRepository.resetNextEventData() eventRepository.clearEvents() } else { - eventRepository.saveEvents( - sortedEvents - ) - eventRepository.saveNextEventData(filteredEventList.first()) + eventRepository.saveEvents(sortedEvents) + //eventRepository.saveNextEventData(filteredEventList.first()) } } catch (ignored: java.lang.Exception) { - } } } else { @@ -179,48 +145,22 @@ class UpdateCalendarService : Service() { } eventRepository.close() - UpdatesReceiver.setUpdates(this@UpdateCalendarService) - MainWidget.updateWidget(this@UpdateCalendarService) + UpdatesReceiver.setUpdates(context) + MainWidget.updateWidget(context) EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent()) - - stopSelf() } - return START_STICKY + return Result.success() } - override fun onDestroy() { - super.onDestroy() - job?.cancel() - job = null - } - - private fun getCalendarSyncNotification(): Notification { - with(NotificationManagerCompat.from(this)) { - // Create channel - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { - createNotificationChannel( - NotificationChannel( - getString(R.string.calendar_sync_notification_channel_id), - getString(R.string.calendar_sync_notification_channel_name), - NotificationManager.IMPORTANCE_LOW - ).apply { - description = getString(R.string.calendar_sync_notification_channel_description) - } - ) - } - - val builder = NotificationCompat.Builder(this@UpdateCalendarService, getString(R.string.calendar_sync_notification_channel_id)) - .setSmallIcon(R.drawable.ic_stat_notification) - .setContentTitle(getString(R.string.calendar_sync_notification_title)) - .setOngoing(true) - .setColor(ContextCompat.getColor(this@UpdateCalendarService, R.color.colorAccent)) - - // Main intent that open the activity - builder.setContentIntent(PendingIntent.getActivity(this@UpdateCalendarService, 0, Intent(this@UpdateCalendarService, MainActivity::class.java), PendingIntent.FLAG_UPDATE_CURRENT)) - - return builder.build() + companion object { + fun enqueue(context: Context) { + WorkManager.getInstance(context.applicationContext).enqueueUniqueWork( + "UpdateCalendarWorker", + ExistingWorkPolicy.REPLACE, + OneTimeWorkRequestBuilder().build() + ) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/services/WeatherWorker.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/services/WeatherWorker.kt new file mode 100644 index 0000000..edf3c43 --- /dev/null +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/services/WeatherWorker.kt @@ -0,0 +1,107 @@ +package com.tommasoberlose.anotherwidget.services + +import android.Manifest +import android.content.Context +import android.location.Location +import android.location.LocationManager +import androidx.work.CoroutineWorker +import androidx.work.ExistingPeriodicWorkPolicy +import androidx.work.ExistingWorkPolicy +import androidx.work.OneTimeWorkRequestBuilder +import androidx.work.PeriodicWorkRequestBuilder +import androidx.work.WorkManager +import androidx.work.WorkerParameters +import com.google.android.gms.common.ConnectionResult +import com.google.android.gms.common.GoogleApiAvailability +import com.google.android.gms.location.LocationServices +import com.google.android.gms.tasks.Tasks +import com.tommasoberlose.anotherwidget.R +import com.tommasoberlose.anotherwidget.global.Preferences +import com.tommasoberlose.anotherwidget.helpers.WeatherHelper +import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi +import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment +import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import org.greenrobot.eventbus.EventBus +import java.util.concurrent.TimeUnit + +class WeatherWorker(private val context: Context, params: WorkerParameters) : + CoroutineWorker(context, params) { + + override suspend fun doWork(): Result { + when { + Preferences.customLocationAdd != "" -> { + withContext(Dispatchers.IO) { + WeatherNetworkApi(context).updateWeather() + } + } + context.checkGrantedPermission(Manifest.permission.ACCESS_COARSE_LOCATION) -> { + if (GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) + == ConnectionResult.SUCCESS + ) { + LocationServices.getFusedLocationProviderClient(context).lastLocation + } 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 + } + } + Tasks.forResult(location) + }.addOnCompleteListener { task -> + val networkApi = WeatherNetworkApi(context) + if (task.isSuccessful) { + val location = task.result + if (location != null) { + Preferences.customLocationLat = location.latitude.toString() + Preferences.customLocationLon = location.longitude.toString() + } + } + + CoroutineScope(Dispatchers.IO).launch { + networkApi.updateWeather() + } + EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent()) + } + } + else -> { + Preferences.weatherProviderLocationError = context.getString(R.string.weather_provider_error_missing_location) + Preferences.weatherProviderError = "" + WeatherHelper.removeWeather(context) + EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent()) + } + } + return Result.success() + } + + companion object { + fun enqueue(context: Context) { + WorkManager.getInstance(context.applicationContext).enqueueUniqueWork( + "OneTimeWeatherWorker", + ExistingWorkPolicy.REPLACE, + OneTimeWorkRequestBuilder().build() + ) + } + + fun enqueue(context: Context, interval: Long, unit: TimeUnit) { + WorkManager.getInstance(context.applicationContext).enqueueUniquePeriodicWork( + "WeatherWorker", + ExistingPeriodicWorkPolicy.REPLACE, + PeriodicWorkRequestBuilder(interval, unit).build() + ) + } + + fun cancel(context: Context) { + WorkManager.getInstance(context.applicationContext).cancelUniqueWork( + "WeatherWorker" + ) + } + } +} diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/tabs/CustomDateActivity.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/tabs/CustomDateActivity.kt index 93c2914..b267704 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/tabs/CustomDateActivity.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/tabs/CustomDateActivity.kt @@ -169,6 +169,7 @@ class CustomDateActivity : AppCompatActivity() { isDateCapitalize = viewModel.isDateCapitalize.value ?: true isDateUppercase = viewModel.isDateUppercase.value ?: false } + com.tommasoberlose.anotherwidget.ui.widgets.MainWidget.updateWidget(this) super.onBackPressed() } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/tabs/WeatherProviderActivity.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/tabs/WeatherProviderActivity.kt index fc41a16..5296a44 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/tabs/WeatherProviderActivity.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/tabs/WeatherProviderActivity.kt @@ -57,9 +57,7 @@ class WeatherProviderActivity : AppCompatActivity() { updateListItem() binding.loader.isVisible = true - lifecycleScope.launch { - WeatherHelper.updateWeather(this@WeatherProviderActivity) - } + WeatherHelper.updateWeather(this@WeatherProviderActivity) } .clicked(R.id.radioButton) { if (Preferences.weatherProvider != provider.rawValue) { @@ -72,9 +70,7 @@ class WeatherProviderActivity : AppCompatActivity() { updateListItem() binding.loader.isVisible = true - lifecycleScope.launch { - WeatherHelper.updateWeather(this@WeatherProviderActivity) - } + WeatherHelper.updateWeather(this@WeatherProviderActivity) } .checked(R.id.radioButton, provider.rawValue == Preferences.weatherProvider) .with(R.id.text2) { @@ -92,10 +88,8 @@ class WeatherProviderActivity : AppCompatActivity() { } .clicked(R.id.action_configure) { BottomSheetWeatherProviderSettings(this) { - lifecycleScope.launch { - binding.loader.isVisible = true - WeatherHelper.updateWeather(this@WeatherProviderActivity) - } + binding.loader.isVisible = true + WeatherHelper.updateWeather(this@WeatherProviderActivity) }.show() } .visibility(R.id.action_configure, if (/*WeatherHelper.isKeyRequired(provider) && */provider.rawValue == Preferences.weatherProvider) View.VISIBLE else View.GONE) diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/SettingsFragment.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/SettingsFragment.kt index 20f441c..23637b1 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/SettingsFragment.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/SettingsFragment.kt @@ -206,15 +206,13 @@ class SettingsFragment : Fragment() { .animate() .rotation((binding.actionRefreshIcon.rotation - binding.actionRefreshIcon.rotation % 360f) + 360f) .withEndAction { - viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) { - try { - WeatherHelper.updateWeather(requireContext()) - CalendarHelper.updateEventList(requireContext()) - MediaPlayerHelper.updatePlayingMediaInfo(requireContext()) - ActiveNotificationsHelper.clearLastNotification(requireContext()) - } catch (ex: Exception) { - ex.printStackTrace() - } + try { + WeatherHelper.updateWeather(requireContext()) + CalendarHelper.updateEventList(requireContext()) + MediaPlayerHelper.updatePlayingMediaInfo(requireContext()) + ActiveNotificationsHelper.clearLastNotification(requireContext()) + } catch (ex: Exception) { + ex.printStackTrace() } } .start() diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/WeatherFragment.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/WeatherFragment.kt index 93189c0..e93e1c0 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/WeatherFragment.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/WeatherFragment.kt @@ -134,7 +134,7 @@ class WeatherFragment : Fragment() { } private fun checkLocationPermission() { - if (requireActivity().checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION)) { + if (requireActivity().checkGrantedPermission(Manifest.permission.ACCESS_COARSE_LOCATION)) { binding.locationPermissionAlert.isVisible = false } else if (Preferences.customLocationAdd == "") { binding.locationPermissionAlert.isVisible = true @@ -177,9 +177,7 @@ class WeatherFragment : Fragment() { .addOnSelectItemListener { value -> if (value != Preferences.weatherTempUnit) { Preferences.weatherTempUnit = value - viewLifecycleOwner.lifecycleScope.launch { - WeatherHelper.updateWeather(requireContext()) - } + WeatherHelper.updateWeather(requireContext()) } }.show() } @@ -208,9 +206,7 @@ class WeatherFragment : Fragment() { if (resultCode == Activity.RESULT_OK) { when (requestCode) { Constants.RESULT_CODE_CUSTOM_LOCATION -> { - viewLifecycleOwner.lifecycleScope.launch { - WeatherHelper.updateWeather(requireContext()) - } + WeatherHelper.updateWeather(requireContext()) } //RequestCode.WEATHER_PROVIDER_REQUEST_CODE.code -> { //} @@ -222,15 +218,14 @@ class WeatherFragment : Fragment() { private fun requirePermission() { Dexter.withContext(requireContext()) .withPermissions( - Manifest.permission.ACCESS_FINE_LOCATION + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.ACCESS_COARSE_LOCATION ).withListener(object: MultiplePermissionsListener { override fun onPermissionsChecked(report: MultiplePermissionsReport?) { report?.let { - if (report.areAllPermissionsGranted()) { + if (report.grantedPermissionResponses.isNotEmpty()) { checkLocationPermission() - viewLifecycleOwner.lifecycleScope.launch { - WeatherHelper.updateWeather(requireContext()) - } + WeatherHelper.updateWeather(requireContext()) } } } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/AlignedWidget.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/AlignedWidget.kt index a7ad254..e498fe4 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/AlignedWidget.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/AlignedWidget.kt @@ -58,7 +58,7 @@ class AlignedWidget(val context: Context, val rightAligned: Boolean = false) { context, appWidgetId, IntentHelper.getWidgetUpdateIntent(context), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent(R.id.widget_shape_background, refreshIntent) @@ -103,7 +103,7 @@ class AlignedWidget(val context: Context, val rightAligned: Boolean = false) { val i = Intent(context, WidgetClickListenerReceiver::class.java) i.action = Actions.ACTION_OPEN_WEATHER_INTENT - val weatherPIntent = PendingIntent.getBroadcast(context, widgetID, i, 0) + val weatherPIntent = PendingIntent.getBroadcast(context, widgetID, i, PendingIntent.FLAG_IMMUTABLE) views.setOnClickPendingIntent(R.id.weather_rect, weatherPIntent) views.setOnClickPendingIntent(R.id.weather_sub_line_rect, weatherPIntent) @@ -133,7 +133,7 @@ class AlignedWidget(val context: Context, val rightAligned: Boolean = false) { context, widgetID, IntentHelper.getCalendarIntent(context), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent(R.id.date_rect, calPIntent) views.setViewVisibility(R.id.first_line_rect, View.VISIBLE) @@ -170,7 +170,7 @@ class AlignedWidget(val context: Context, val rightAligned: Boolean = false) { context, NewCalendarEventReceiver::class.java ).apply { action = Actions.ACTION_GO_TO_NEXT_EVENT }, - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) ) @@ -184,7 +184,7 @@ class AlignedWidget(val context: Context, val rightAligned: Boolean = false) { context, widgetID, IntentHelper.getEventIntent(context, nextEvent), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent(R.id.next_event_rect, eventIntent) views.setImageViewBitmap( @@ -221,7 +221,7 @@ class AlignedWidget(val context: Context, val rightAligned: Boolean = false) { context, widgetID, IntentHelper.getGoogleMapsIntentFromAddress(context, nextEvent.address), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent(R.id.sub_line_rect, mapIntent) } else { @@ -229,7 +229,7 @@ class AlignedWidget(val context: Context, val rightAligned: Boolean = false) { context, widgetID, IntentHelper.getCalendarIntent(context, nextEvent.startDate), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent(R.id.sub_line_rect, pIntentDetail) } @@ -249,7 +249,7 @@ class AlignedWidget(val context: Context, val rightAligned: Boolean = false) { context, widgetID, IntentHelper.getMusicIntent(context), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent(R.id.sub_line_rect, musicIntent) showSomething = true @@ -264,7 +264,7 @@ class AlignedWidget(val context: Context, val rightAligned: Boolean = false) { context, widgetID, IntentHelper.getClockIntent(context), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent(R.id.sub_line_rect, alarmIntent) showSomething = true @@ -280,7 +280,7 @@ class AlignedWidget(val context: Context, val rightAligned: Boolean = false) { context, widgetID, IntentHelper.getBatteryIntent(), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent(R.id.sub_line_rect, batteryIntent) showSomething = true @@ -300,7 +300,7 @@ class AlignedWidget(val context: Context, val rightAligned: Boolean = false) { context, widgetID, IntentHelper.getFitIntent(context), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent(R.id.sub_line_rect, fitIntent) showSomething = true @@ -321,7 +321,7 @@ class AlignedWidget(val context: Context, val rightAligned: Boolean = false) { context, widgetID, IntentHelper.getNotificationIntent(context), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent( R.id.sub_line_rect, @@ -339,7 +339,7 @@ class AlignedWidget(val context: Context, val rightAligned: Boolean = false) { } } Constants.GlanceProviderId.EVENTS -> { - if (Preferences.showEventsAsGlanceProvider&& Preferences.showEvents && context.checkGrantedPermission( + if (Preferences.showEventsAsGlanceProvider && Preferences.showEvents && context.checkGrantedPermission( Manifest.permission.READ_CALENDAR) && nextEvent != null) { val pIntentDetail = IntentHelper.getPendingIntent( context, @@ -349,7 +349,7 @@ class AlignedWidget(val context: Context, val rightAligned: Boolean = false) { nextEvent, forceEventDetails = true ), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent( R.id.sub_line_rect, @@ -363,7 +363,7 @@ class AlignedWidget(val context: Context, val rightAligned: Boolean = false) { if (Preferences.showWeatherAsGlanceProvider && Preferences.showWeather && Preferences.weatherIcon != "") { val i = Intent(context, WidgetClickListenerReceiver::class.java) i.action = Actions.ACTION_OPEN_WEATHER_INTENT - val weatherPIntent = PendingIntent.getBroadcast(context, widgetID, i, 0) + val weatherPIntent = PendingIntent.getBroadcast(context, widgetID, i, PendingIntent.FLAG_IMMUTABLE) views.setOnClickPendingIntent( R.id.sub_line_rect, diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/ClockWidget.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/ClockWidget.kt index b505cbd..ad0d975 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/ClockWidget.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/ClockWidget.kt @@ -41,7 +41,7 @@ class ClockWidget(val context: Context) { context, widgetID, IntentHelper.getClockIntent(context), - 0 + PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent(R.id.time, clockPIntent) views.setOnClickPendingIntent(R.id.time_am_pm, clockPIntent) diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/StandardWidget.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/StandardWidget.kt index f13a53c..d9b1e83 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/StandardWidget.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/StandardWidget.kt @@ -60,7 +60,7 @@ class StandardWidget(val context: Context) { context, appWidgetId, IntentHelper.getWidgetUpdateIntent(context), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent(R.id.widget_shape_background, refreshIntent) @@ -105,7 +105,7 @@ class StandardWidget(val context: Context) { val i = Intent(context, WidgetClickListenerReceiver::class.java) i.action = Actions.ACTION_OPEN_WEATHER_INTENT - val weatherPIntent = PendingIntent.getBroadcast(context, widgetID, i, 0) + val weatherPIntent = PendingIntent.getBroadcast(context, widgetID, i, PendingIntent.FLAG_IMMUTABLE) views.setOnClickPendingIntent(R.id.weather_rect, weatherPIntent) views.setOnClickPendingIntent(R.id.weather_sub_line_rect, weatherPIntent) @@ -135,7 +135,7 @@ class StandardWidget(val context: Context) { context, widgetID, IntentHelper.getCalendarIntent(context), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent(R.id.date_rect, calPIntent) views.setViewVisibility(R.id.first_line_rect, View.VISIBLE) @@ -178,7 +178,7 @@ class StandardWidget(val context: Context) { context, NewCalendarEventReceiver::class.java ).apply { action = Actions.ACTION_GO_TO_NEXT_EVENT }, - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) ) @@ -197,7 +197,7 @@ class StandardWidget(val context: Context) { context, NewCalendarEventReceiver::class.java ).apply { action = Actions.ACTION_GO_TO_PREVIOUS_EVENT }, - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) ) @@ -213,7 +213,7 @@ class StandardWidget(val context: Context) { context, widgetID, IntentHelper.getEventIntent(context, nextEvent), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent(R.id.next_event_rect, eventIntent) views.setViewVisibility(R.id.next_event_rect, View.VISIBLE) @@ -246,7 +246,7 @@ class StandardWidget(val context: Context) { context, widgetID, IntentHelper.getGoogleMapsIntentFromAddress(context, nextEvent.address), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent(R.id.sub_line_rect, mapIntent) } else { @@ -254,7 +254,7 @@ class StandardWidget(val context: Context) { context, widgetID, IntentHelper.getCalendarIntent(context, nextEvent.startDate), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent(R.id.sub_line_rect, pIntentDetail) } @@ -280,7 +280,7 @@ class StandardWidget(val context: Context) { context, widgetID, IntentHelper.getMusicIntent(context), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent(R.id.sub_line_rect, musicIntent) showSomething = true @@ -295,7 +295,7 @@ class StandardWidget(val context: Context) { context, widgetID, IntentHelper.getClockIntent(context), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent(R.id.sub_line_rect, alarmIntent) showSomething = true @@ -311,7 +311,7 @@ class StandardWidget(val context: Context) { context, widgetID, IntentHelper.getBatteryIntent(), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent(R.id.sub_line_rect, batteryIntent) showSomething = true @@ -331,7 +331,7 @@ class StandardWidget(val context: Context) { context, widgetID, IntentHelper.getFitIntent(context), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent(R.id.sub_line_rect, fitIntent) showSomething = true @@ -352,7 +352,7 @@ class StandardWidget(val context: Context) { context, widgetID, IntentHelper.getNotificationIntent(context), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent( R.id.sub_line_rect, @@ -370,7 +370,7 @@ class StandardWidget(val context: Context) { } } Constants.GlanceProviderId.EVENTS -> { - if (Preferences.showEventsAsGlanceProvider&& Preferences.showEvents && context.checkGrantedPermission( + if (Preferences.showEventsAsGlanceProvider && Preferences.showEvents && context.checkGrantedPermission( Manifest.permission.READ_CALENDAR) && nextEvent != null) { val pIntentDetail = IntentHelper.getPendingIntent( context, @@ -380,7 +380,7 @@ class StandardWidget(val context: Context) { nextEvent, forceEventDetails = true ), - PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) views.setOnClickPendingIntent( R.id.sub_line_rect, @@ -394,7 +394,7 @@ class StandardWidget(val context: Context) { if (Preferences.showWeatherAsGlanceProvider && Preferences.showWeather && Preferences.weatherIcon != "") { val i = Intent(context, WidgetClickListenerReceiver::class.java) i.action = Actions.ACTION_OPEN_WEATHER_INTENT - val weatherPIntent = PendingIntent.getBroadcast(context, widgetID, i, 0) + val weatherPIntent = PendingIntent.getBroadcast(context, widgetID, i, PendingIntent.FLAG_IMMUTABLE) views.setOnClickPendingIntent( R.id.sub_line_rect, diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/utils/Extensions.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/utils/Extensions.kt index 6ac8f10..236733f 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/utils/Extensions.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/utils/Extensions.kt @@ -214,6 +214,14 @@ fun Context.checkGrantedPermission(permission: String): Boolean { return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED } +fun android.app.AlarmManager.setExactIfCanSchedule(type: Int, triggerAtMillis: Long, operation: android.app.PendingIntent) { + // uncomment the following check after bumping compileSdkVersion/targetSdkVersion to 31 + //if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.S || canScheduleExactAlarms()) + setExact(type, triggerAtMillis, operation) + //else + // set(type, triggerAtMillis, operation) +} + fun Context.getCurrentWallpaper(): Drawable? = try { WallpaperManager.getInstance(this).drawable } catch (e: Exception) {