diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index bdacddf..dec76d4 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/app/build.gradle b/app/build.gradle index 75c3b4d..f554e0e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,7 @@ android { applicationId "com.tommasoberlose.anotherwidget" minSdkVersion 23 targetSdkVersion 29 - versionCode 69 + versionCode 70 versionName "2.0.5" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/release/app-release.aab b/app/release/app-release.aab deleted file mode 100644 index a194054..0000000 Binary files a/app/release/app-release.aab and /dev/null differ diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/components/BottomSheetMenu.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/components/BottomSheetMenu.kt index 4d1cd6c..0a300f7 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/components/BottomSheetMenu.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/components/BottomSheetMenu.kt @@ -1,17 +1,11 @@ package com.tommasoberlose.anotherwidget.components -import android.app.Dialog import android.content.Context -import android.os.Bundle import android.view.View -import android.view.ViewGroup -import androidx.annotation.MenuRes -import androidx.appcompat.widget.AppCompatTextView import androidx.core.content.ContextCompat import androidx.core.view.isVisible import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialogFragment -import com.google.android.material.card.MaterialCardView import com.tommasoberlose.anotherwidget.R import kotlinx.android.synthetic.main.bottom_sheet_menu.view.* import kotlinx.android.synthetic.main.bottom_sheet_menu_item.view.* @@ -21,7 +15,7 @@ import kotlinx.android.synthetic.main.bottom_sheet_menu_item.view.* * theme which sets a rounded background to the dialog * and doesn't dim the navigation bar */ -open class BottomSheetMenu(context: Context, private val header: String? = null, private val isMultiSelection: Boolean = false) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) { +open class BottomSheetMenu(context: Context, private val header: String? = null, private val message: String? = null, private val isMessageWarning: Boolean = false, private val isMultiSelection: Boolean = false) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) { private val items: ArrayList> = ArrayList() private var selectedRes: ArrayList = ArrayList() @@ -60,6 +54,10 @@ open class BottomSheetMenu(context: Context, private val header: String? = nu view.header.isVisible = header != null view.header_text.text = header ?: "" + view.warning_text.isVisible = message != null + view.warning_text.text = message ?: "" + view.warning_text.setTextColor(ContextCompat.getColor(context, if (isMessageWarning) R.color.warningColorText else R.color.colorSecondaryText)) + // Menu for (item in items) { if (item.value != null) { diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/db/EventRepository.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/db/EventRepository.kt index fc42acf..884eca3 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/db/EventRepository.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/db/EventRepository.kt @@ -5,6 +5,7 @@ import com.chibatching.kotpref.bulk import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.models.Event import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver +import com.tommasoberlose.anotherwidget.services.UpdatesWorker import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget import io.realm.Realm import io.realm.RealmResults @@ -41,7 +42,7 @@ class EventRepository(val context: Context) { fun getNextEvent(): Event? = realm.where(Event::class.java).equalTo("id", Preferences.nextEventId).findFirst() ?: realm.where(Event::class.java).findFirst() - fun getEventById(id: Long): Event? = realm.where(Event::class.java).equalTo("id", id).findFirst() + fun getEventByEventId(id: Long): Event? = realm.where(Event::class.java).equalTo("eventID", id).findFirst() fun goToNextEvent() { val eventList = realm.where(Event::class.java).findAll() @@ -56,7 +57,7 @@ class EventRepository(val context: Context) { } else { resetNextEventData() } - UpdatesReceiver.setUpdates(context) + UpdatesWorker.setUpdates(context) MainWidget.updateWidget(context) } @@ -73,7 +74,7 @@ class EventRepository(val context: Context) { } else { resetNextEventData() } - UpdatesReceiver.setUpdates(context) + UpdatesWorker.setUpdates(context) MainWidget.updateWidget(context) } 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 9d857de..484652a 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/AlarmHelper.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/AlarmHelper.kt @@ -23,4 +23,14 @@ object AlarmHelper { "" } } + + fun isAlarmProbablyWrong(context: Context): Boolean { + with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) { + val alarm = nextAlarmClock + return ( + alarm != null + && alarm.triggerTime - Calendar.getInstance().timeInMillis < 5 * 60 * 1000 + ) + } + } } \ No newline at end of file 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 ae8e423..eb92b32 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/CalendarHelper.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/CalendarHelper.kt @@ -10,6 +10,7 @@ import com.tommasoberlose.anotherwidget.db.EventRepository import com.tommasoberlose.anotherwidget.models.Event import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver +import com.tommasoberlose.anotherwidget.services.UpdatesWorker import com.tommasoberlose.anotherwidget.ui.activities.MainActivity import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission @@ -124,7 +125,7 @@ object CalendarHelper { eventRepository.resetNextEventData() } - UpdatesReceiver.setUpdates(context) + UpdatesWorker.setUpdates(context) Log.d("ciao", "force update? 7") MainWidget.updateWidget(context) 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 8899b8a..9c29342 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/IntentHelper.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/IntentHelper.kt @@ -9,9 +9,9 @@ import android.net.Uri import android.provider.AlarmClock import android.provider.CalendarContract import android.provider.CalendarContract.Events -import android.util.Log import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.models.Event +import java.util.* object IntentHelper { @@ -63,9 +63,15 @@ object IntentHelper { } fun getCalendarIntent(context: Context): Intent { + val calendarUri = CalendarContract.CONTENT_URI + .buildUpon() + .appendPath("time") + .appendPath(Date(Calendar.getInstance().timeInMillis).toString()) + .build() return when (Preferences.calendarAppPackage) { "" -> { Intent(Intent.ACTION_MAIN).apply { +// data = calendarUri addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) addCategory(Intent.CATEGORY_APP_CALENDAR) } @@ -77,12 +83,14 @@ object IntentHelper { val pm: PackageManager = context.packageManager try { pm.getLaunchIntentForPackage(Preferences.calendarAppPackage)!!.apply { +// data = calendarUri addCategory(Intent.CATEGORY_LAUNCHER) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) } } catch (e: Exception) { e.printStackTrace() Intent(Intent.ACTION_MAIN).apply { +// data = calendarUri addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) addCategory(Intent.CATEGORY_APP_CALENDAR) } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/SettingsStringHelper.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/SettingsStringHelper.kt index 5dcaa16..ef83b94 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/SettingsStringHelper.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/SettingsStringHelper.kt @@ -73,7 +73,7 @@ object SettingsStringHelper { return "" } TimeUnit.MILLISECONDS.toHours(difference) < 12 -> { - return DateUtils.getRelativeTimeSpanString(start, now, DateUtils.HOUR_IN_MILLIS).toString() + return DateUtils.getRelativeTimeSpanString(start, now, DateUtils.HOUR_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString() } eventDate.dayOfYear == nowDate.plusDays(1).dayOfYear -> { return String.format("%s", context.getString(R.string.tomorrow)) @@ -82,7 +82,7 @@ object SettingsStringHelper { return String.format("%s", context.getString(R.string.today)) } else -> { - return DateUtils.getRelativeTimeSpanString(start, now, DateUtils.DAY_IN_MILLIS).toString() + return DateUtils.getRelativeTimeSpanString(start, now, DateUtils.DAY_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString() } } 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 84c7c4a..5b77d72 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt @@ -75,7 +75,8 @@ class UpdatesReceiver : BroadcastReceiver() { AlarmManagerCompat.setExactAndAllowWhileIdle(this, AlarmManager.RTC_WAKEUP, if (event.endDate > 60 *1000) event.endDate else 120000, - PendingIntent.getBroadcast(context, 0, Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_TIME_UPDATE }, 0)) + PendingIntent.getBroadcast(context, 0, Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_TIME_UPDATE }, 0) + ) } } } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdatesWorker.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdatesWorker.kt new file mode 100644 index 0000000..c974712 --- /dev/null +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdatesWorker.kt @@ -0,0 +1,67 @@ +package com.tommasoberlose.anotherwidget.services + +import android.app.AlarmManager +import android.content.Context +import android.util.Log +import androidx.work.* +import com.tommasoberlose.anotherwidget.db.EventRepository +import com.tommasoberlose.anotherwidget.models.Event +import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget +import org.joda.time.Period +import java.util.* +import java.util.concurrent.TimeUnit + +class UpdatesWorker(appContext: Context, workerParams: WorkerParameters) : Worker(appContext, workerParams) { + override fun doWork(): Result { + Log.d("ciao1", "update ok: $inputData") + val repo = EventRepository(applicationContext) + val event = repo.getEventByEventId(inputData.getLong(EVENT_ID, -1)) + event?.let { + scheduleEventUpdate(applicationContext, it) + } + MainWidget.updateWidget(applicationContext) + return Result.success() + } + + companion object { + private const val JOB_TAG = "UPDATES_WORKER" + private const val EVENT_ID = "event_id" + + fun setUpdates(context: Context) { + removeUpdates(context) + + EventRepository(context).getEvents().forEach { event -> + scheduleEventUpdate(context, event) + } + } + + private fun scheduleEventUpdate(context: Context, event: Event) { + val workManager = WorkManager.getInstance(context) + val now = Calendar.getInstance().apply { + set(Calendar.SECOND, 0) + set(Calendar.MILLISECOND, 0) + } + if (event.startDate > now.timeInMillis) { + val diff = Period(now.timeInMillis, event.startDate) + workManager.enqueueUniqueWork("UPDATES_JOB_ONE_TIME_${event.eventID}", ExistingWorkPolicy.REPLACE, OneTimeWorkRequestBuilder() + .setInputData(Data.Builder().putLong(EVENT_ID, event.eventID).build()) + .setInitialDelay(if (diff.minutes > 0) diff.minutes.toLong() else 60L, TimeUnit.MINUTES) + .addTag(JOB_TAG) + .build() + ) + Log.d("ciao1", "next update ${Date(now.timeInMillis + (if (diff.minutes > 0) diff.minutes.toLong() else 60L) * 60 * 1000)}") + } else if (event.endDate > now.timeInMillis) { + // Update the widget one second after the event is finished + workManager.enqueueUniqueWork("UPDATES_JOB_ONE_TIME_END_${event.eventID}", ExistingWorkPolicy.REPLACE, OneTimeWorkRequestBuilder() + .setInitialDelay(event.endDate - now.timeInMillis, TimeUnit.MILLISECONDS) + .addTag(JOB_TAG) + .build() + ) + } + } + + fun removeUpdates(context: Context) { + WorkManager.getInstance(context).cancelAllWorkByTag(JOB_TAG) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/ClockSettingsFragment.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/ClockSettingsFragment.kt index f99585c..eb96e65 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/ClockSettingsFragment.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/ClockSettingsFragment.kt @@ -1,7 +1,13 @@ package com.tommasoberlose.anotherwidget.ui.fragments import android.app.Activity +import android.app.AlarmManager +import android.content.BroadcastReceiver +import android.content.Context import android.content.Intent +import android.content.IntentFilter +import android.content.pm.ApplicationInfo +import android.content.pm.PackageManager import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -19,12 +25,16 @@ import com.tommasoberlose.anotherwidget.databinding.FragmentClockSettingsBinding import com.tommasoberlose.anotherwidget.global.Constants import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.global.RequestCode +import com.tommasoberlose.anotherwidget.helpers.AlarmHelper import com.tommasoberlose.anotherwidget.ui.activities.ChooseApplicationActivity import com.tommasoberlose.anotherwidget.ui.activities.MainActivity import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel +import com.tommasoberlose.anotherwidget.utils.toast import kotlinx.android.synthetic.main.fragment_clock_settings.* import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import java.lang.Exception + class ClockSettingsFragment : Fragment() { @@ -58,6 +68,7 @@ class ClockSettingsFragment : Fragment() { super.onActivityCreated(savedInstanceState) setupListener() + updateNextAlarmWarningUi() } private fun subscribeUi( @@ -156,6 +167,38 @@ class ClockSettingsFragment : Fragment() { } } + private fun updateNextAlarmWarningUi() { + show_next_alarm_warning.isVisible = AlarmHelper.isAlarmProbablyWrong(requireContext()) + with(requireContext().getSystemService(Context.ALARM_SERVICE) as AlarmManager) { + val alarm = nextAlarmClock + if (alarm != null) { + val pm = requireContext().packageManager as PackageManager + val appNameOrPackage = try { + pm.getApplicationLabel(pm.getApplicationInfo(nextAlarmClock.showIntent.creatorPackage ?: "", 0)) + } catch (e: Exception) { + nextAlarmClock.showIntent.creatorPackage + } + show_next_alarm_warning.text = getString(R.string.next_alarm_warning).format(appNameOrPackage) + } + } + } + + private val nextAlarmChangeBroadcastReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context?, intent: Intent?) { + updateNextAlarmWarningUi() + } + } + + override fun onStart() { + super.onStart() + activity?.registerReceiver(nextAlarmChangeBroadcastReceiver, IntentFilter(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)) + } + + override fun onStop() { + activity?.unregisterReceiver(nextAlarmChangeBroadcastReceiver) + super.onStop() + } + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { if (resultCode == Activity.RESULT_OK && requestCode == RequestCode.CLOCK_APP_REQUEST_CODE.code) { Preferences.bulk { diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/WeatherSettingsFragment.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/WeatherSettingsFragment.kt index 6bf2441..3623ce4 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/WeatherSettingsFragment.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/WeatherSettingsFragment.kt @@ -137,7 +137,7 @@ class WeatherSettingsFragment : Fragment() { private fun checkLocationPermission() { // Background permission - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && activity?.checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION) == true) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && activity?.checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION) == true && activity?.checkGrantedPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION) != true) { requirePermission() } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/MainWidget.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/MainWidget.kt index d69ec99..d797ceb 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/MainWidget.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/MainWidget.kt @@ -31,6 +31,7 @@ import com.tommasoberlose.anotherwidget.helpers.WidgetHelper.reduceDimensionWith import com.tommasoberlose.anotherwidget.receivers.NewCalendarEventReceiver import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver import com.tommasoberlose.anotherwidget.receivers.WidgetClickListenerReceiver +import com.tommasoberlose.anotherwidget.services.UpdatesWorker import com.tommasoberlose.anotherwidget.services.WeatherWorker import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission import com.tommasoberlose.anotherwidget.utils.getCapWordString @@ -69,7 +70,7 @@ class MainWidget : AppWidgetProvider() { override fun onDisabled(context: Context) { if (getWidgetCount(context) == 0) { - UpdatesReceiver.removeUpdates(context) + UpdatesWorker.removeUpdates(context) WeatherWorker.removeUpdates(context) } } 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 c9cacc0..983b727 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/utils/Extensions.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/utils/Extensions.kt @@ -32,8 +32,8 @@ import java.util.* fun PackageManager.missingSystemFeature(name: String): Boolean = !hasSystemFeature(name) -fun Context.toast(message: String) { - val toast = Toast.makeText(this, message, Toast.LENGTH_SHORT) +fun Context.toast(message: String, long: Boolean = false) { + val toast = Toast.makeText(this, message, if (long) Toast.LENGTH_LONG else Toast.LENGTH_SHORT) // toast.setGravity(Gravity.CENTER, 0, 0) toast.show() } diff --git a/app/src/main/res/layout/bottom_sheet_menu.xml b/app/src/main/res/layout/bottom_sheet_menu.xml index 24d7057..b34fe5d 100644 --- a/app/src/main/res/layout/bottom_sheet_menu.xml +++ b/app/src/main/res/layout/bottom_sheet_menu.xml @@ -26,6 +26,22 @@ android:id="@+id/header_text" android:text="" android:textColor="@color/colorPrimaryText"/> + + Alpha Background color Transparent + The next alarm clock seems to be wrong.\nIt has been set by %s. \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index be7f149..3784a7c 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -185,4 +185,5 @@ Alpha Background color Transparent + The next alarm clock seems to be wrong.\nIt has been set by %s. \ No newline at end of file diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 208e5db..20ede23 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -184,4 +184,5 @@ Trasparenza Colore background Trasparente + La sveglia sembra impostata male.\nĂˆ stata impostata dall\'app %s. \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 0740b90..f514051 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -28,6 +28,7 @@ #99000000 #FBD8D8 #E93B3B + #FB8C00 #efefef diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b169fa5..a083602 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -196,4 +196,5 @@ Grant permission Alpha Transparent + The next alarm clock seems to be wrong.\nIt has been set by %s. diff --git a/tasksintegration/build/intermediates/bundle_manifest/debug/bundle-manifest/AndroidManifest.xml b/tasksintegration/build/intermediates/bundle_manifest/debug/bundle-manifest/AndroidManifest.xml index c21ea2c..81fe1ee 100644 --- a/tasksintegration/build/intermediates/bundle_manifest/debug/bundle-manifest/AndroidManifest.xml +++ b/tasksintegration/build/intermediates/bundle_manifest/debug/bundle-manifest/AndroidManifest.xml @@ -3,7 +3,7 @@ xmlns:dist="http://schemas.android.com/apk/distribution" featureSplit="tasksintegration" package="com.tommasoberlose.anotherwidget" - android:versionCode="68" + android:versionCode="70" android:versionName="2.0.5" > 8 9