This commit is contained in:
Tommaso Berlose 2020-05-06 16:16:31 +02:00
parent e2503decd2
commit 2e684e0902
29 changed files with 185 additions and 26 deletions

Binary file not shown.

View File

@ -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"

Binary file not shown.

View File

@ -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<T>(context: Context, private val header: String? = null, private val isMultiSelection: Boolean = false) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
open class BottomSheetMenu<T>(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<MenuItem<T>> = ArrayList()
private var selectedRes: ArrayList<T> = ArrayList()
@ -60,6 +54,10 @@ open class BottomSheetMenu<T>(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) {

View File

@ -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)
}

View File

@ -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
)
}
}
}

View File

@ -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)

View File

@ -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)
}

View File

@ -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()
}
}

View File

@ -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)
)
}
}
}

View File

@ -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<WeatherWorker>()
.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<WeatherWorker>()
.setInitialDelay(event.endDate - now.timeInMillis, TimeUnit.MILLISECONDS)
.addTag(JOB_TAG)
.build()
)
}
}
fun removeUpdates(context: Context) {
WorkManager.getInstance(context).cancelAllWorkByTag(JOB_TAG)
}
}
}

View File

@ -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 {

View File

@ -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()
}

View File

@ -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)
}
}

View File

@ -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()
}

View File

@ -26,6 +26,22 @@
android:id="@+id/header_text"
android:text=""
android:textColor="@color/colorPrimaryText"/>
<androidx.appcompat.widget.AppCompatTextView
android:textAppearance="@style/TextAppearance.MaterialComponents.Button"
app:textAllCaps="false"
android:letterSpacing="0"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="start"
android:textAlignment="viewStart"
android:layout_marginTop="-8dp"
android:paddingBottom="8dp"
android:paddingLeft="32dp"
android:paddingRight="32dp"
android:textSize="15sp"
android:id="@+id/warning_text"
android:text=""
android:textColor="@color/warningColorText"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="1dp"

View File

@ -251,6 +251,14 @@
android:layout_height="wrap_content"
android:id="@+id/show_next_alarm_label"
style="@style/AnotherWidget.Settings.Subtitle"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/AnotherWidget.Settings.Title"
android:textSize="14sp"
android:visibility="gone"
android:id="@+id/show_next_alarm_warning"
android:textColor="@color/warningColorText" />
</LinearLayout>
</LinearLayout>
<LinearLayout

View File

@ -205,4 +205,5 @@
<string name="alpha">Alpha</string>
<string name="settings_background_color_title">Background color</string>
<string name="transparent">Transparent</string>
<string name="next_alarm_warning">The next alarm clock seems to be wrong.\nIt has been set by %s.</string>
</resources>

View File

@ -185,4 +185,5 @@
<string name="alpha">Alpha</string>
<string name="settings_background_color_title">Background color</string>
<string name="transparent">Transparent</string>
<string name="next_alarm_warning">The next alarm clock seems to be wrong.\nIt has been set by %s.</string>
</resources>

View File

@ -184,4 +184,5 @@
<string name="alpha">Trasparenza</string>
<string name="settings_background_color_title">Colore background</string>
<string name="transparent">Trasparente</string>
<string name="next_alarm_warning">La sveglia sembra impostata male.\nÈ stata impostata dall\'app %s.</string>
</resources>

View File

@ -28,6 +28,7 @@
<color name="colorSecondaryText">#99000000</color>
<color name="errorColorBackground">#FBD8D8</color>
<color name="errorColorText">#E93B3B</color>
<color name="warningColorText">#FB8C00</color>
<color name="disabledButtonBackground">#efefef</color>
</resources>

View File

@ -196,4 +196,5 @@
<string name="action_grant_permission">Grant permission</string>
<string name="alpha">Alpha</string>
<string name="transparent">Transparent</string>
<string name="next_alarm_warning">The next alarm clock seems to be wrong.\nIt has been set by %s.</string>
</resources>

View File

@ -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" >
<uses-sdk

View File

@ -1,4 +1,4 @@
#Wed May 06 11:30:08 CEST 2020
#Wed May 06 15:59:56 CEST 2020
base.0=/Users/tommaso/Documents/MyCode/another-widget/tasksintegration/build/intermediates/dex/debug/mergeProjectDexDebug/out/classes.dex
path.0=classes.dex
renamed.0=classes.dex

View File

@ -4,7 +4,7 @@
featureSplit="tasksintegration"
package="com.tommasoberlose.anotherwidget"
android:targetSandboxVersion="2"
android:versionCode="68"
android:versionCode="70"
android:versionName="2.0.5" >
<uses-sdk

View File

@ -3,7 +3,7 @@
3 xmlns:dist="http://schemas.android.com/apk/distribution"
4 featureSplit="tasksintegration"
5 package="com.tommasoberlose.anotherwidget"
6 android:versionCode="68"
6 android:versionCode="70"
7 android:versionName="2.0.5" >
8
9 <uses-sdk

View File

@ -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" >
<uses-sdk

View File

@ -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" >
<uses-sdk android:targetSdkVersion="29" />