Attempt to address Android 16 widget changes

pull/3881/head
Alex Baker 3 months ago
parent 04ab41f622
commit e6bbc8d361

@ -6,12 +6,10 @@ import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.media.RingtoneManager
import android.net.Uri
import android.os.Binder
import androidx.compose.material3.DisplayMode
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.core.app.NotificationCompat
import androidx.core.net.toUri
import androidx.documentfile.provider.DocumentFile
import androidx.preference.PreferenceManager
@ -30,8 +28,6 @@ import org.tasks.extensions.Context.getResourceUri
import org.tasks.kmp.org.tasks.themes.ColorProvider.BLUE_500
import org.tasks.themes.ThemeBase
import org.tasks.time.DateTime
import org.tasks.time.DateTimeUtils2.currentTimeMillis
import org.tasks.time.ONE_WEEK
import timber.log.Timber
import java.io.File
import java.net.URI

@ -1,12 +1,15 @@
package org.tasks.widget
import android.app.Activity
import android.appwidget.AppWidgetManager
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.tasks.R
@ -25,23 +28,45 @@ class AppWidgetManager @Inject constructor(
?.getAppWidgetIds(ComponentName(context, TasksWidget::class.java))
?: intArrayOf()
fun reconfigureWidgets(vararg appWidgetIds: Int) = scope.launch(Dispatchers.IO) {
fun reconfigureWidgets(vararg appWidgetIds: Int) = scope.launch {
Timber.d("reconfigureWidgets(${appWidgetIds.joinToString()})")
val ids = appWidgetIds.takeIf { it.isNotEmpty() } ?: widgetIds
val intent = Intent(context, TasksWidget::class.java)
intent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
intent.putExtra(
AppWidgetManager.EXTRA_APPWIDGET_IDS,
appWidgetIds.takeIf { it.isNotEmpty() } ?: widgetIds)
context.sendBroadcast(intent)
.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids)
.apply { action = AppWidgetManager.ACTION_APPWIDGET_UPDATE }
context.sendOrderedBroadcast(
intent,
null,
object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
scope.launch {
Timber.d("Update widgets after reconfigure: ${appWidgetIds.joinToString { it.toString() }}")
// I don't like it, but this seems to give Android enough time to update
// the cache, and I don't have time to rewrite this in Glance right now
delay(100)
notifyAppWidgetViewDataChanged(ids)
}
}
},
null,
Activity.RESULT_OK,
null,
null
)
}
fun updateWidgets() = scope.launch(Dispatchers.IO) {
fun updateWidgets() = scope.launch {
val appWidgetIds = widgetIds
Timber.d("updateWidgets: ${appWidgetIds.joinToString()}")
withContext(Dispatchers.Main) {
appWidgetManager?.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.list_view)
}
Timber.d("updateWidgets: ${appWidgetIds.joinToString { it.toString() }}")
notifyAppWidgetViewDataChanged(appWidgetIds)
}
fun exists(id: Int) = appWidgetManager?.getAppWidgetInfo(id) != null
}
private suspend fun notifyAppWidgetViewDataChanged(appWidgetIds: IntArray) = withContext(Dispatchers.Main) {
appWidgetManager?.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.list_view)
}
}

@ -5,10 +5,10 @@ import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.View
import android.widget.RemoteViews
import androidx.core.net.toUri
import com.todoroo.andlib.utility.AndroidUtilities.atLeastS
import com.todoroo.astrid.activity.MainActivity.Companion.FINISH_AFFINITY
import dagger.hilt.android.AndroidEntryPoint
@ -35,13 +35,11 @@ class TasksWidget : AppWidgetProvider() {
@Inject @ApplicationContext lateinit var context: Context
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
appWidgetIds.forEach { appWidgetId ->
Timber.d("onUpdate appWidgetIds=${appWidgetIds.joinToString { it.toString() }}")
appWidgetIds.forEach { id ->
try {
val options = appWidgetManager.getAppWidgetOptions(appWidgetId)
appWidgetManager.updateAppWidget(
appWidgetId,
createWidget(context, appWidgetId, options)
)
val options = appWidgetManager.getAppWidgetOptions(id)
appWidgetManager.updateAppWidget(id, createWidget(context, id, options))
} catch (e: Exception) {
Timber.e(e)
}
@ -54,10 +52,12 @@ class TasksWidget : AppWidgetProvider() {
appWidgetId: Int,
newOptions: Bundle
) {
Timber.d("onAppWidgetOptionsChanged appWidgetId=$appWidgetId")
appWidgetManager.updateAppWidget(
appWidgetId,
createWidget(context, appWidgetId, newOptions)
)
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.list_view)
}
private fun createWidget(context: Context, id: Int, options: Bundle): RemoteViews {
@ -69,6 +69,8 @@ class TasksWidget : AppWidgetProvider() {
val filter = runBlocking {
defaultFilterProvider.getFilterFromPreference(widgetPreferences.filterId)
}
Timber.d("createWidget id=$id filter=$filter")
return RemoteViews(context.packageName, R.layout.scrollable_widget).apply {
if (settings.showHeader) {
setViewVisibility(R.id.widget_header, View.VISIBLE)
@ -87,11 +89,12 @@ class TasksWidget : AppWidgetProvider() {
opacity = widgetPreferences.footerOpacity,
)
setOnClickPendingIntent(R.id.empty_view, getOpenListIntent(context, filter, id))
val cacheBuster = Uri.parse("tasks://widget/" + currentTimeMillis())
val cacheBuster = "tasks://widget/${currentTimeMillis()}".toUri()
setRemoteAdapter(
R.id.list_view,
Intent(context, TasksWidgetAdapter::class.java)
.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id)
.putExtra("extra_cache_buster", cacheBuster)
.setData(cacheBuster)
)
setPendingIntentTemplate(R.id.list_view, getPendingIntentTemplate(context))
@ -232,4 +235,4 @@ class TasksWidget : AppWidgetProvider() {
private const val COMPACT_MAX = 275
private const val FLAGS = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
}
}
}

@ -13,6 +13,7 @@ import org.tasks.markdown.MarkdownProvider
import org.tasks.preferences.DefaultFilterProvider
import org.tasks.preferences.Preferences
import org.tasks.tasklist.HeaderFormatter
import timber.log.Timber
import javax.inject.Inject
@AndroidEntryPoint
@ -32,6 +33,7 @@ class TasksWidgetAdapter : RemoteViewsService() {
val filter = runBlocking {
defaultFilterProvider.getFilterFromPreference(widgetPreferences.filterId)
}
Timber.d("onGetViewFactory $filter")
return TasksWidgetViewFactory(
subtasksHelper,
widgetPreferences,

@ -66,9 +66,12 @@ internal class TasksWidgetViewFactory(
chipProvider.isDark = settings.isDark
}
override fun onCreate() {}
override fun onCreate() {
Timber.d("onCreate widgetId:$widgetId filter:$filter")
}
override fun onDataSetChanged() {
Timber.v("onDataSetChanged $filter")
runBlocking {
val collapsed = widgetPreferences.collapsed
tasks = SectionedDataSource(
@ -87,7 +90,9 @@ internal class TasksWidgetViewFactory(
}
}
override fun onDestroy() {}
override fun onDestroy() {
Timber.d("onDestroy widgetId:$widgetId")
}
override fun getCount() = tasks.size.coerceAtMost(taskLimit)

Loading…
Cancel
Save